﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Win32;
using System.Drawing;
using System.Diagnostics;
using System.Reflection;
using System.Data;
using System.IO;

public delegate void LookupInvoker(TextBoxHandle txtHandle, LookupMode eMode);
public delegate DataRowEx LookupInvokerEx(TextBoxHandle txtHandle, LookupMode eMode);
public delegate DataRowEx GridLookupInvoker(DataGridViewCell currentCell, string columnValue, LookupMode eMode);
public delegate void ListItemInvoker(ListViewItem itm);


internal struct LookupStructure
{
    public object LookupValue;
    public string LookupCode;
    public string LookupName;
    public DataRowEx LookupData;
}

public enum LookupMode : int
{
    SelectData = 0,
    CheckData = 1,
    GetData = 2,
    CacheData = 4
}

public enum DataInputState
{
    BrowseMode = 0,
    ViewMode = 1,
    EditMode = 2,
    AddMode = 4,
    CopyMode = 8,
    VersionMode = 16,
    ReviewMode = 32,
    ApproveMode = 64
}

/// <summary>
/// Các loại kiểu dữ liệu input
/// </summary>
public enum DataInputType
{
    TextData = 0,
    NumberData = 1,
    IntegerData = 2,
    DateData = 3,
    TimeData = 4,
    EmailData = 5,
    WebData = 6,
    RegExData = 7,
    TimeExData = 8
}


public class TransparentLabel : Control
{
    public TransparentLabel()
    {
        TabStop = false;
        this.Size = new Size(5, 10);
    }
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle = cp.ExStyle | 0x20;
            return cp;
        }
    }
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // do nothing 
    }
    protected override void OnPaint(PaintEventArgs e)
    {
        using (SolidBrush brush = new SolidBrush(ForeColor))
        {
            e.Graphics.DrawString(Text, Font, brush, -1, 0);
        }
    }
}

/// <summary>
/// Combobox item, phục vụ Bild dữ liệu gồm text, value
/// </summary>
public class ComboboxItem
{
    public string Text { get; set; }
    public object Value { get; set; }

    public ComboboxItem(string text, object value)
    {
        Text = text;
        Value = value;
    }
}

/// <summary>
/// Tương tự Combobox item
/// </summary>
public class ListBoxItem
{
    //Class phục vụ cho việc bind list từ IDataReader
    string _DisplayField;

    string _ValueField;

    public ListBoxItem()
    {
    }

    public ListBoxItem(string iValue, string sName = "")
    {
        _DisplayField = sName;
        _ValueField = iValue;
    }

    public string DisplayField
    {
        get { return _DisplayField; }
        set { _DisplayField = value; }
    }

    public string ValueField
    {
        get { return _ValueField; }
        set { _ValueField = value; }
    }
}

/// <summary>
/// Các hàm tiện ích, thao tác với form
/// </summary>
public class FormGlobals
{
    /// <summary>
    /// Lớp formfield, gồm các trường, phục vụ set control, để fill dữ liệu tự động theo cấu trúc từ database
    /// </summary>
    private struct FormField
    {
        public string FieldName;
        public string ControlType;
        public string ControlName;
        public int DataLength;
        public byte DataScale;
        public string DataFormat;
        public string DataType;
        public bool Required;
        public object MaxValue;
        //
        public int PropertyIndex;
        public int DataColummIndex;
    }

    /// <summary>
    /// Các thuộc tính cơ bản của Form
    /// </summary>
    private struct FormProperty
    {
        public bool ControlBox;
        public FormBorderStyle FormBorderStyle;
        public bool ShowIcon;
        public bool ShowInTaskbar;
        public FormStartPosition StartPosition;
        public Point Location;
        public Size Size;
    }



    internal static Dictionary<string, Bitmap> ui_ImageResource = new Dictionary<string, Bitmap>();
    /// <summary>
    /// Khởi tạo các Resource cho chương trình
    /// </summary>
    /// <param name="uiResource"></param>
    public static void App_InitResource(Type uiResource)
    {
        foreach (PropertyInfo propertyInfo in uiResource.GetProperties(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic))
        {
            if (!(propertyInfo.PropertyType.Name == "Bitmap"))
                continue;
            if (ui_ImageResource.ContainsKey(propertyInfo.Name))
            {
                ui_ImageResource[propertyInfo.Name.ToUpper()] = (System.Drawing.Bitmap)propertyInfo.GetValue(null, null);
            }
            else
            {
                ui_ImageResource.Add(propertyInfo.Name.ToUpper(), (System.Drawing.Bitmap)propertyInfo.GetValue(null, null));
            }
        }
    }

    /// <summary>
    /// Tự động set Icon cho menu, ảnh lấy từ resource, với tên ảnh chính là tên menu
    /// </summary>
    /// <param name="mnuRoot"></param>
    public static void Menu_AutoSetIcon(MenuStrip mnuRoot)
    {
        foreach (ToolStripItem tsi in mnuRoot.Items)
        {
            if (tsi is ToolStripMenuItem)
            {
                ToolStripMenu_AutoSetIcon((ToolStripMenuItem)tsi);
            }
            else if (tsi.Image == null && ui_ImageResource.ContainsKey(tsi.Name))
            {
                tsi.Image = ui_ImageResource[tsi.Name];
            }
        }
    }

    private static void ToolStripMenu_AutoSetIcon(ToolStripMenuItem item)
    {
        foreach (ToolStripItem itmChild in item.DropDownItems)
        {
            if (itmChild is ToolStripMenuItem)
                ToolStripMenu_AutoSetIcon((ToolStripMenuItem)itmChild);
            //
            if (itmChild.Image == null && ui_ImageResource.ContainsKey(itmChild.Name.ToUpper()))
            {
                itmChild.Image = ui_ImageResource[itmChild.Name.ToUpper()];
            }
        }
    }


    /// <summary>
    /// Khởi tạo menu chính của hệ thống, hứng sự kiện Click
    /// </summary>
    /// <param name="mnuRoot"></param>
    /// <param name="arrItem"></param>
    /// <param name="itemClick"></param>
    public static void Menu_Init(ToolStripMenuItem mnuRoot, List<ToolStripItem> arrItem, ToolStripItemClickedEventHandler itemClick)
    {
        foreach (ToolStripItem item in arrItem)
        {
            if (item is ToolStripMenuItem)
            {
                ((ToolStripMenuItem)item).DropDownItemClicked += itemClick;
            }
        }
        mnuRoot.DropDownItems.Clear();
        mnuRoot.DropDownItems.AddRange(arrItem.ToArray());
        ((ToolStripMenuItem)mnuRoot).DropDownItemClicked += itemClick;
        FormGlobals.Menu_AutoShortcut(mnuRoot);
    }

    /// <summary>
    /// Tự động tạo ShortCut cho menu item
    /// </summary>
    /// <param name="mnuRoot"></param>
    public static void Menu_AutoShortcut(ToolStripMenuItem mnuRoot)
    {
        int iIndex = 0;
        foreach (ToolStripItem itmChild in mnuRoot.DropDownItems)
        {
            if (itmChild is ToolStripMenuItem)
            {
                Menu_AutoShortcut((ToolStripMenuItem)itmChild);
                iIndex += 1;
                if ((!itmChild.Text.StartsWith("&")))
                {
                    itmChild.Text = string.Format("&{0}. ", iIndex.ToString("X")) + itmChild.Text;
                }
            }
        }
    }

    /// <summary>
    /// Thêm một item cho menu
    /// </summary>
    /// <param name="arrItem"></param>
    /// <param name="menuName"></param>
    /// <param name="menuText"></param>
    public static void Menu_AddItem(List<ToolStripItem> arrItem, string menuName, string menuText)
    {
        Menu_AddItem(arrItem, menuName, menuText, null);
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem, string menuName, string menuText, Type formType)
    {
        Menu_AddItem(arrItem, menuName, menuText, formType, null);
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem, string menuName, string menuText, Type formType, object initParam)
    {
        ToolStripMenuItem itemMenu = Menu_NewItem(menuName, menuText, formType, initParam);
        arrItem.Add(itemMenu);
    }

    public static void Menu_AddItem(List<ToolStripItem> arrItem)
    {
        arrItem.Add(new ToolStripSeparator());
    }

    public static ToolStripItem Menu_NewItem()
    {
        return new ToolStripSeparator();
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText)
    {
        return Menu_NewItem(menuName, menuText, null);
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText, Type formType)
    {
        return Menu_NewItem(menuName, menuText, formType, null);
    }

    public static ToolStripMenuItem Menu_NewItem(string menuName, string menuText, Type formType, object initParam)
    {
        ToolStripMenuItem itemMenu = new ToolStripMenuItem();
        itemMenu.Name = menuName;
        itemMenu.Text = menuText;
        itemMenu.Tag = initParam;
        //
        if ((formType != null))
        {
            if (m_dicMenuForm.ContainsKey(menuName))
                m_dicMenuForm.Remove(menuName);
            m_dicMenuForm.Add(menuName, formType);
        }
        //
        return itemMenu;
    }
    private static Dictionary<string, Type> m_dicMenuForm = new Dictionary<string, Type>();
    /// <summary>
    /// Lấy form base tương ứng với menu, phục vụ show form tự động theo menu
    /// </summary>
    /// <param name="menuName"></param>
    /// <returns></returns>
    public static FormBase Menu_GetForm(string menuName)
    {
        if (!m_dicMenuForm.ContainsKey(menuName))
            return null;
        FormBase objForm = Activator.CreateInstance(m_dicMenuForm[menuName]) as FormBase;
        //Return m_dicMenuForm(menuName)
        objForm.MenuName = menuName;
        return objForm;
    }

    public static bool Menu_ShowForm(ToolStripItem menuItem)
    {
        if (string.IsNullOrEmpty(menuItem.Name) || menuItem is ToolStripSeparator)
            return true;
        if (!m_dicMenuForm.ContainsKey(menuItem.Name))
            return false;
        FormBase objForm = Activator.CreateInstance(m_dicMenuForm[menuItem.Name]) as FormBase;
        if ((objForm != null))
        {
            objForm.MenuName = menuItem.Name;
            objForm.InitValue = menuItem.Tag;
            objForm.Text = menuItem.Text.Substring(menuItem.Text.IndexOf(". ") + 2);
            objForm.Show_Form();
            return true;
        }
        else
        {
            return false;
        }
    }

    /// <summary>
    /// Docpanel, khung hiển thị chính nội dung các form, khi bấm vào menu
    /// </summary>
    public static WeifenLuo.WinFormsUI.Docking.DockPanel dockPanel;

    public static FormBase Form_FindInTab(FormBase fChild)
    {
        return Form_FindInTab(fChild, fChild.Text);
    }

    public static FormBase Form_FindInTab(FormBase fChild, string fText)
    {
        //FormBase tabItem = default(FormBase);
        FormBase f = default(FormBase);
        foreach (Form tabItem in (FormGlobals.dockPanel.Documents))
        {
            if (tabItem is FormBase)
            {
                f = tabItem as FormBase;
                if (f.FormId != fChild.FormId && f.Name + "|" + f.Text == fChild.Name + "|" + fText)
                {
                    return f;
                }
            }
        }
        return null;
    }


    #region font, style, set enable, visible
    public static void Control_SetFont(Control objControl, string fontName)
    {
        Control_SetFont(objControl, fontName, objControl.Font.Size);
    }

    public static void Control_SetFont(Control objControl, string fontName, float fontSize)
    {
        objControl.Font = new Font(fontName, fontSize, objControl.Font.Style);
    }

    /// <summary>
    /// Đặt style cho các control của formbase
    /// </summary>
    /// <param name="objControl"></param>
    /// <param name="style"></param>
    /// <param name="bOverwrite"></param>
    static internal void Control_SetStyle(Control objControl, string style, bool bOverwrite = false)
    {
        Font f = default(Font);
        string[] arrStyle = null;
        arrStyle = style.Split(new char[] { ';' });
        if (arrStyle.Length > 0 && (bOverwrite || objControl.ForeColor.IsSystemColor || objControl.ForeColor.ToString() == "Color [A=255, R=0, G=0, B=0]" || objControl.ForeColor == objControl.Parent.ForeColor))
            objControl.ForeColor = App_GetColor(arrStyle[0]);
        if (arrStyle.Length > 1)
        {
            float fontSize = objControl.Font.Size;
            if (arrStyle.Length == 3)
                fontSize = (float)Convert.ToDecimal(arrStyle[2]);
            if (fontSize < 0)
                fontSize = objControl.Font.Size;
            switch (arrStyle[1])
            {
                case "Bold":
                    f = new Font(objControl.Font.FontFamily, fontSize, FontStyle.Bold);
                    break;
                case "Italic":
                    f = new Font(objControl.Font.FontFamily, fontSize, FontStyle.Italic);
                    break;
                default:
                    f = new Font(objControl.Font.FontFamily, fontSize, FontStyle.Regular);
                    break;
            }
            objControl.Font = f;
        }
    }

    static internal Font Control_StyleFont(Font fontInit, string style)
    {
        Font f = default(Font);
        string[] arrStyle = null;
        arrStyle = style.Split(new char[] { ';' });
        if (arrStyle.Length > 1)
        {
            switch (arrStyle[1])
            {
                case "Bold":
                    f = new Font(fontInit, FontStyle.Bold);
                    break;
                case "Italic":
                    f = new Font(fontInit, FontStyle.Italic);
                    break;
                default:
                    f = new Font(fontInit, FontStyle.Regular);
                    break;
            }
        }
        else
        {
            f = fontInit;
        }
        return f;
    }

    static internal Color Control_StyleColor(Color colorInit, string style)
    {
        Color retVal = default(Color);
        string[] arrStyle = null;
        arrStyle = style.Split(new char[] { ';' });
        if (arrStyle.Length > 0)
        {
            retVal = App_GetColor(arrStyle[0]);
        }
        else
        {
            retVal = colorInit;
        }
        return retVal;
    }

    static internal void Control_SetStyle(DataGridViewCellStyle cellStyle, string style)
    {
        Font f = default(Font);
        string[] arrStyle = null;
        arrStyle = style.Split(new char[] { ';' });
        if (arrStyle.Length > 0)
            cellStyle.ForeColor = App_GetColor(arrStyle[0]);
        if (arrStyle.Length > 1)
        {
            switch (arrStyle[1])
            {
                case "Bold":
                    f = new Font(cellStyle.Font, FontStyle.Bold);
                    break;
                case "Italic":
                    f = new Font(cellStyle.Font, FontStyle.Italic);
                    break;
                default:
                    f = new Font(cellStyle.Font, FontStyle.Regular);
                    break;
            }
            cellStyle.Font = f;
        }
    }

    public static void Control_SetStyle(Control objControl)
    {
        Control_SetStyle(objControl, CS_FONT_NAME, objControl.Font.Size);
    }

    public static void Control_SetStyle(Color bgColor, params Control[] ctrs)
    {
        foreach (Control ctr in ctrs)
            ctr.BackColor = bgColor;
    }


    public static void Control_SetStyle(Control objControl, string fontName, float fontSize)
    {
        if (Array.IndexOf(FormGlobals.cs_Control_Input, objControl.GetType().Name) >= 0)
        {
            Control_SetStyle(objControl, CS_STYLE_INPUT);
        }
        else if (Array.IndexOf(FormGlobals.cs_Control_Toolbar, objControl.GetType().Name) >= 0)
        {
            Control_SetStyle(objControl, CS_STYLE_TOOLBAR);
        }
        else
        {
            if (objControl.Font != null && objControl.Font.Size > fontSize)
                fontSize = objControl.Font.Size;
            objControl.Font = new Font(fontName, fontSize, objControl.Font.Style);
        }
        if (objControl is DataGridView)
        {
            //Cell
            Control_SetStyle(((DataGridView)objControl).DefaultCellStyle, CS_GRID_CELL);
            //Header
            Control_SetStyle(((DataGridView)objControl).ColumnHeadersDefaultCellStyle, CS_GRID_HEADER);

            ((DataGridView)objControl).ColumnHeadersDefaultCellStyle.Padding = new Padding(3); //đặt padding cho header grid

            return;
        }
        //Label
        else if (objControl is Label)
        {
            if (objControl.Tag == null)
            {
                Control_SetStyle(objControl, CS_STYLE_LABEL);
            }
            else
            {
                switch (objControl.Tag.ToString().ToUpper())
                {
                    case "INFO":
                        Control_SetStyle(objControl, CS_STYLE_INFO);
                        break;
                }
            }
            return;
        }
        //Button
        else if (objControl is Button && objControl.Name.StartsWith("cmd"))
        {
            Control_SetStyle(objControl, CS_STYLE_CMD);
            return;
        }
        //Group box
        else if (objControl is GroupBox && !string.IsNullOrEmpty(objControl.Text))
        {
            Control_SetStyle(objControl, CS_STYLE_GROUP);
        }
        else if (objControl is TreeView)
        {
            Control_SetStyle(objControl, CS_STYLE_INPUT);
            return;
        }
        foreach (Control childControl in objControl.Controls)
        {
            Control_SetStyle(childControl, fontName, fontSize);
        }
    }

    //Fix autocomplete when combobox is suggest & append and combobox mode
    public static void Combobox_SetAutoComplete(ComboBox cbo)
    {
        cbo.DropDown += comboBox_DropDown;
    }

    public static void Combobox_SetAutoComplete(params ComboBox [] cbos)
    {
        foreach(ComboBox cbo in cbos)
            cbo.DropDown += comboBox_DropDown;
    }

    private static void comboBox_DropDown(object sender, EventArgs e)
    {
        ComboBox cbo = (ComboBox)sender;
        cbo.PreviewKeyDown += new PreviewKeyDownEventHandler(comboBox_PreviewKeyDown);
    }

    private static void comboBox_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        ComboBox cbo = (ComboBox)sender;
        cbo.PreviewKeyDown -= comboBox_PreviewKeyDown;
        if (cbo.DroppedDown) cbo.Focus();
    }

    /// <summary>
    /// Đặt kiểu giao diện trình bày phẳng cho control
    /// </summary>
    /// <param name="objControl"></param>
    public static void Control_SetFlat(Control objControl)
    {
        //If objControl.HasChildren And Not TypeOf objControl Is ToolStrip Then
        //    For Each objChild As Control In objControl.Controls
        //        Control_SetFlat(objChild)
        //    Next
        //    Return
        //End If
        //
        bool bDrawRect = false;
        //
        if (objControl is TextBox)
        {
            ((TextBox)objControl).BorderStyle = BorderStyle.FixedSingle;
        }
        else if (objControl is MaskedTextBox)
        {
            ((MaskedTextBox)objControl).BorderStyle = BorderStyle.FixedSingle;
        }
        else if (objControl is Button)
        {
            ((Button)objControl).FlatStyle = FlatStyle.Flat;
        }
        else if (objControl is CheckBox)
        {
            ((CheckBox)objControl).FlatStyle = FlatStyle.Flat;
        }
        else if (objControl is RadioButton)
        {
            ((RadioButton)objControl).FlatStyle = FlatStyle.Flat;
        }
        else if (objControl is ComboBox)
        {
            ((ComboBox)objControl).FlatStyle = FlatStyle.Flat;
            //
            bDrawRect = true;
        }
        else if (objControl is RichTextBox)
        {
            ((RichTextBox)objControl).BorderStyle = BorderStyle.None;
            bDrawRect = true;
        }
        else
        {
            if (!(objControl is ToolStrip))
            {
                foreach (Control objChild in objControl.Controls)
                {
                    Control_SetFlat(objChild);
                }
            }
            return;
        }
        //
        if (!bDrawRect)
            return;
        //
        string ctlName = objControl.Name + "_Flat";
        Label ctlLabel = default(Label);
        if ((objControl.Visible || !objControl.FindForm().Visible) && !objControl.Parent.Controls.ContainsKey(ctlName))
        {
            objControl.Height -= 2;
            ctlLabel = new Label();
            ctlLabel.Name = objControl.Name + "_Flat";
            ctlLabel.AutoSize = false;
            ctlLabel.BorderStyle = BorderStyle.FixedSingle;
            ctlLabel.Width = objControl.Width;
            ctlLabel.Height = objControl.Height + 2;
            ctlLabel.Location = objControl.Location;
            objControl.Parent.Controls.Add(ctlLabel);
            ctlLabel.SendToBack();
            //
            objControl.Left += 1;
            objControl.Width -= 2;
            objControl.Top += 1;
            //
            objControl.VisibleChanged += objControl_VisibleChanged;
        }
        //'
    }

    private static void objControl_VisibleChanged(object sender, System.EventArgs e)
    {
        if ((((Control)sender).Parent != null) && (((Control)sender).Parent.Controls.ContainsKey(((Control)sender).Name + "_Flat")))
        {
            ((Control)sender).Parent.Controls[((Control)sender).Name + "_Flat"].Visible = ((Control)sender).Visible;
        }
    }

    public static void Control_SetState(Control objControl, DataInputState sState)
    {
        //Purpose: 
        //   'Set trạng thái cho các ô nhập liệu theo trạng thái nhập liệu
        //Parameters: 
        //   objControl : đối tượng chứa nhóm Control (thường là Panel và GroupBox)
        //   sState: trạng thái nhập liệu
        //Notes
        //               
        foreach (Control mControl in objControl.Controls)
        {
            switch (mControl.GetType().Name)
            {
                case "TextBox":
                case "ComboBox":
                case "DataGridView":
                    SetControlViewOnly(mControl, true, true, (sState == DataInputState.ViewMode));
                    break;
                case "ListBox":
                case "TreeView":
                    if (mControl.Parent.Parent is System.Windows.Forms.Form)
                    {
                        mControl.Enabled = (sState == DataInputState.ViewMode);
                    }
                    else
                    {
                        mControl.Enabled = !(sState == DataInputState.ViewMode);
                    }
                    break;
                case "Button":
                case "RadioButton":
                case "CheckBox":
                    mControl.Enabled = !(sState == DataInputState.ViewMode);
                    break;
                default:
                    if (mControl.HasChildren)
                    {
                        Control_SetState(mControl, sState);
                    }
                    break;
            }
        }
    }

    /// <summary>
    /// Set ViewOnly cho control, nếu control có childer => tất cả children cũng viewonly theo
    /// </summary>
    public static void Control_SetViewOnly(Control objControl)
    {
        Control_SetViewOnly(objControl, true);
    }

    /// <summary>
    /// Set ViewOnly cho control, nếu control có childer => tất cả children cũng viewonly theo
    /// </summary>
    public static void Control_SetViewOnly(bool viewOnly, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetViewOnly(mControl, viewOnly);
        }
    }

    /// <summary>
    /// Set ViewOnly cho control, nếu control có childer => tất cả children cũng viewonly theo
    /// </summary>
    public static void Control_SetViewOnly(params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetViewOnly(mControl, true);
        }
    }

    public static void ToolStrip_SetViewOnly(bool viewOnly, params ToolStripItem[] arrControl)
    {
        foreach (ToolStripItem mControl in arrControl)
        {
            mControl.Enabled = !viewOnly;
        }
    }

    public static void ToolStrip_SetVisible(bool visible, params ToolStripItem[] arrControl)
    {
        foreach (ToolStripItem mControl in arrControl)
        {
            mControl.Visible = visible;
        }
    }

    public static void ToolStrip_SetViewOnly(params ToolStripItem[] arrControl)
    {
        ToolStrip_SetViewOnly(false, arrControl);
    }

    public static void Control_SetViewOnly(Control objControl, string[] exceptControl)
    {
        Control_SetViewOnly(objControl, true, true, true, exceptControl);
    }

    public static void Control_SetViewOnly(Control objControl, string[] exceptControl, bool bSetChildOnly)
    {
        Control_SetViewOnly(objControl, true, bSetChildOnly, true, exceptControl);
    }

    public static void Control_SetViewOnly(Control objControl, bool bViewOnly)
    {
        Control_SetViewOnly(objControl, bViewOnly, true);
    }

    public static void Control_SetViewOnly(Control objControl, bool bViewOnly, bool bSetChildOnly)
    {
        Control_SetViewOnly(objControl, bViewOnly, bSetChildOnly, true);
    }

    public static void Control_SetViewOnly(Control objControl, bool bViewOnly, bool bSetChildOnly, bool bForceVisible)
    {
        Control_SetViewOnly(objControl, bViewOnly, bSetChildOnly, bForceVisible, null);
    }

    private static void Control_SetViewOnly(Control objControl, bool bViewOnly, bool bSetChildOnly, bool bForceVisible, string[] exceptControl)
    {
        //Purpose: 
        //   Đặt trạng thái ViewOnly cho các ô nhập liệu
        //Parameters: 
        //   objControl : đối tượng Control hoặc đối tượng chứa nhóm Control cần set view only          
        //   bSetChildOnly : chỉ set cho các Child control, không đệ quy để tìm các Child of Child
        //   bForceVisible : không kiểm tra thuộc tính visible
        //Notes
        //                  

        if (objControl.HasChildren && !(objControl is DataGridView))// || objControl is RadioButtonList))
        {
            System.Windows.Forms.Form objForm = default(System.Windows.Forms.Form);
            if (!bForceVisible)
            {
                objForm = objControl.FindForm();
                if ((objForm != null))
                {
                    if (!objForm.Visible)
                    {
                        //Form_BeginInit(ref objForm, true);
                    }
                    else
                    {
                        objForm = null;
                    }
                }
            }

            foreach (Control mControl in objControl.Controls)
            {
                SetControlViewOnly(mControl, bSetChildOnly, bForceVisible, bViewOnly, exceptControl);
            }

            if ((objForm != null))
            {
                //Form_EndInit(objForm);
            }
        }
        else
        {
            SetControlViewOnly(objControl, bSetChildOnly, true, bViewOnly);
        }
    }

    //Thủ tục dùng để SetViewOnly đệ quy 
    private static bool Control_ViewOnly_Disable = false;

    private static void SetControlViewOnly(Control objControl, bool bSetChildOnly, bool bForceVisible = false, bool bSetOn = true, string[] exceptControl = null)
    {
        if (!objControl.HasChildren || objControl is DataGridView) //|| objControl is RadioButtonList)
        {
            if (objControl.Visible | bForceVisible)
            {
                //Kiem tra danh sach loai tru
                if ((exceptControl != null) && Array.IndexOf(exceptControl, objControl.Name) >= 0)
                    return;
                //Rẽ nhánh theo kiểu ô nhập liệu

                //objControl.Enabled = Control_ViewOnly_Disable; //Control ở trạng thái ViewOnly thì kiêm luôn cả Disable

                switch (objControl.GetType().Name)
                {
                    case "TextBox":

                        //Set ReadOnly, BackColor, BorderStyle
                        ((TextBox)objControl).ReadOnly = bSetOn;
                        if (bSetOn)
                        {
                            ((TextBox)objControl).BackColor = System.Drawing.ColorTranslator.FromHtml(CS_STYLE_VIEW);
                            //CType(objControl, TextBox).BorderStyle = BorderStyle.FixedSingle
                        }
                        else
                        {
                            ((TextBox)objControl).BackColor = SystemColors.Window;
                            //CType(objControl, TextBox).BorderStyle = BorderStyle.Fixed3D
                        }
                        break;
                    case "MaskedTextBox":
                        //Set ReadOnly, BackColor, BorderStyle
                        ((MaskedTextBox)objControl).ReadOnly = bSetOn;
                        if (bSetOn)
                        {
                            ((MaskedTextBox)objControl).BackColor = System.Drawing.ColorTranslator.FromHtml(CS_STYLE_VIEW);
                            //CType(objControl, TextBox).BorderStyle = BorderStyle.FixedSingle
                        }
                        else
                        {
                            ((MaskedTextBox)objControl).BackColor = SystemColors.Window;
                            //CType(objControl, TextBox).BorderStyle = BorderStyle.Fixed3D
                        }
                        break;
                    case "ComboBox":
                        //Khởi tạo 1 TextBox ReadOnly để hiển thị thay thế
                        TextBox objTextBox = default(TextBox);
                        objTextBox = objControl.Parent.Controls[objControl.Name + "_View"] as TextBox;
                        Control objFlat = default(Control);
                        objFlat = objControl.Parent.Controls[objControl.Name + "_Flat"];
                        if (bSetOn)
                        {
                            if (objTextBox == null)
                            {
                                objTextBox = new TextBox();
                                objTextBox.Location = objControl.Location;
                                objTextBox.Size = objControl.Size;
                                objTextBox.Anchor = objControl.Anchor;
                                objTextBox.Font = objControl.Font;
                                objTextBox.Name = objControl.Name + "_View";
                                objControl.Parent.Controls.Add(objTextBox);
                                Control_SetViewOnly(objTextBox, true);
                                if (((ComboBox)objControl).FlatStyle == FlatStyle.Flat)
                                {
                                    objTextBox.BorderStyle = BorderStyle.FixedSingle;
                                    objTextBox.Height = objControl.Height + 2;
                                }
                            }
                            objTextBox.Visible = true;
                            objTextBox.BringToFront();
                            objTextBox.Text = objControl.Text;
                        }
                        else
                        {
                            if ((objTextBox != null))
                                objTextBox.Visible = false;
                        }
                        if ((objFlat != null))
                            objFlat.Visible = !bSetOn;
                        objControl.Visible = !bSetOn;
                        break;
                    case "Button":
                    case "CheckedListBox":
                    case "RadioButton":
                    case "CheckBox":
                    case "TreeView":
                    case "RadioButtonList":
                        //Set Enabled cho các Control khác
                        if (!objControl.Name.EndsWith("_btnLookup"))
                        {
                            objControl.Enabled = !bSetOn;
                        }
                        break;
                    case "DataGridView":
                        DataGridView objGrid = (DataGridView)objControl;
                        objGrid.ReadOnly = bSetOn;
                        objGrid.AllowUserToAddRows = !bSetOn;
                        objGrid.AllowUserToDeleteRows = !bSetOn;
                        if (bSetOn)
                        {
                            objGrid.RowHeadersWidth = 30;
                            objGrid.RowHeadersVisible = false;
                            objGrid.MultiSelect = false;
                            objGrid.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
                        }
                        else
                        {
                            objGrid.RowHeadersWidth = 45;
                            objGrid.RowHeadersVisible = true;
                            objGrid.SelectionMode = DataGridViewSelectionMode.CellSelect;
                            objGrid.MultiSelect = true;
                        }
                        foreach (DataGridViewColumn mCol in objGrid.Columns)
                        {
                            if (mCol is DataGridViewButtonColumn)
                            {
                                mCol.Visible = !bSetOn;
                            }
                        }

                        break;
                    case "RichTextBox":
                        RichTextBox objRichText = (RichTextBox)objControl;
                        objRichText.ReadOnly = bSetOn;
                        if (bSetOn)
                        {
                            objRichText.BackColor = System.Drawing.ColorTranslator.FromHtml(CS_STYLE_VIEW);
                        }
                        else
                        {
                            objRichText.BackColor = SystemColors.Window;
                        }
                        break;
                    default:
                        //Các trường hợp khác
                        //Bỏ qua
                        return;
                }
                //Invisible/visible require
                Control ctl = objControl.Parent.Controls[objControl.Name + "_Required"];
                if ((ctl != null))
                    ctl.Visible = !bSetOn;
                //Set TabStop
                objControl.TabStop = !bSetOn;
            }
        }
        else
        {
            if ((objControl.Visible | bForceVisible) & bSetChildOnly == false)
            {
                foreach (Control mControl in objControl.Controls)
                {
                    SetControlViewOnly(mControl, bSetChildOnly, bForceVisible, bSetOn, exceptControl);
                }
            }
        }
    }

    public static void Button_SetViewOnly(Control objControl)
    {
        Button_SetViewOnly(objControl, true);
    }

    //Đặt trạng thái ViewOnly cho các nút command
    public static void Button_SetViewOnly(Control objControl, bool bViewOnly)
    {
        foreach (Control mControl in objControl.Controls)
        {
            if (!(mControl.Name == "cmdExit" || mControl.Name == "btnExit" || mControl.Name.IndexOf("cmdView") > -1 || mControl.Name.IndexOf("btnView") > -1))
            {
                mControl.Visible = !bViewOnly;
                //Else
                //    mControl.Visible = bViewOnly
            }
        }
    }

    /// <summary>
    /// Gán context menu cho button, khi click vào button, sẽ xổ contextmenu
    /// </summary>
    /// <param name="btn"></param>
    /// <param name="cms"></param>
    public static void Button_PopupClick(Button btn, ContextMenuStrip cms)
    {
        Button_PopupClick(btn, cms, null);
    }

    /// <summary>
    /// Gán context menu cho button, khi click vào button, sẽ xổ contextmenu
    /// </summary>
    /// <param name="btn"></param>
    /// <param name="cms"></param>
    public static void Button_PopupClick(Button btn, ContextMenuStrip cms, ToolStripItemClickedEventHandler evtHandler)
    {
        btn.Click += Button_Popup_Click;
        btn.Tag = cms;
        if ((evtHandler != null))
        {
            cms.ItemClicked += evtHandler;
        }
    }

    /// <summary>
    /// Gán context menu cho button, khi click vào button, sẽ xổ contextmenu
    /// </summary>
    /// <param name="btn"></param>
    /// <param name="cms"></param>
    private static void Button_Popup_Click(object sender, EventArgs e)
    {
        Button btn = sender as Button;
        System.Drawing.Point mPoint = new System.Drawing.Point(btn.Width, 0);
        ((ContextMenuStrip)btn.Tag).Show(btn, mPoint);
    }

    /// <summary>
    /// Đặt Image tự động cho các control trên Toolbar
    /// </summary>
    /// <param name="toolbar"></param>
    public static void Toolbar_SetImage(ToolStrip toolbar)
    {
        SortedList<int, Button> lstButton = new SortedList<int, Button>();
        foreach (ToolStripItem mControl in toolbar.Items)
        {
            if (mControl is ToolStripButton)
            {
                Toolbar_SetImage((ToolStripButton)mControl);
            }
        }
    }

    public static void Toolbar_SetImage(ToolStripButton button)
    {
        string sName = button.Name.Substring(3);
        if (sName.Contains("_"))
            sName = sName.Substring(0, sName.IndexOf("_"));
        object objRes = GetResouceImage(sName);
        if (objRes is Bitmap)
        {
            button.Image = (System.Drawing.Bitmap)objRes;
            button.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
        }
        else
        {
            return;
        }
        button.ImageAlign = ContentAlignment.MiddleLeft;
        button.TextAlign = ContentAlignment.MiddleRight;
    }

    /// <summary>
    /// Đặt image tự động cho các control trong panel command ở cuối form
    /// </summary>
    /// <param name="pnlCommand"></param>
    public static void Panel_InitCommand(Control pnlCommand)
    {
        SortedList<int, Button> lstButton = new SortedList<int, Button>();
        foreach (Control mControl in pnlCommand.Controls)
        {
            if (mControl is Button)
            {
                int vLeft = mControl.Left;
                while (lstButton.ContainsKey(vLeft))
                {
                    vLeft += 1;
                }
                lstButton.Add(vLeft, (Button)mControl);
                //
                Button_SetImage(mControl);
            }
        }
        //Auto tab index by position
        int tabIndex = 0;
        foreach (Button mButton in lstButton.Values)
        {
            mButton.TabIndex = tabIndex;
            tabIndex += 1;
        }
    }

    private static Bitmap GetResouceImage(string sName)
    {
        Bitmap objRes = default(Bitmap);
        //if (ui_ImageResource.ContainsKey("btn" + sName))
        //{
        //    objRes = ui_ImageResource["btn" + sName];
        //}
        //else if (ui_ImageResource.ContainsKey(sName))
        //{
        //    objRes = ui_ImageResource[sName];
        //}
        //else
        //{
        //    objRes = Resources.ResourceManager.GetObject("btn" + sName) as Bitmap;
        //}
        return objRes;
    }

    public static void Button_SetImage(Control objControl)
    {
        if (objControl is Button)
        {
            string sName = objControl.Name.Substring(3);
            //Support image define in button Tag
            if ((objControl.Tag != null) && objControl.Tag.ToString().StartsWith("btn"))
            {
                sName = objControl.Tag.ToString().Substring(3);
            }
            if (sName.Contains("_"))
                sName = sName.Substring(0, sName.IndexOf("_"));
            object objRes = GetResouceImage(sName);
            if (objRes is Bitmap)
            {
                ((Button)objControl).Image = (System.Drawing.Bitmap)objRes;
            }
            else
            {
                return;
            }
            ((Button)objControl).ImageAlign = ContentAlignment.MiddleLeft;
            ((Button)objControl).TextAlign = ContentAlignment.MiddleRight;
        }
        else
        {
            foreach (Control mControl in objControl.Controls)
            {
                Button_SetImage(mControl);
            }
        }
    }

    /// <summary>
    /// Đặt trạng thái cho nút
    /// </summary>
    /// <param name="objControl"></param>
    /// <param name="sState"></param>
    public static void Button_SetState(Control objControl, DataInputState sState)
    {
        //Purpose: 
        //   'Set trạng thái cho các button theo trạng thái nhập liệu
        //Parameters: 
        //   objControl : đối tượng chứa nhóm Button Control (thường là Panel và GroupBox)
        //   sState: trạng thái nhập liệu
        //Notes
        //     
        string[] arrEditButton = new string[] {
			"Add",
			"Edit",
			"Update",
			"Delete",
			"Copy"
		};
        string[] arrSaveButton = new string[] {
			"Save",
			"OK",
			"Cancel"
		};
        foreach (Control mControl in objControl.Controls)
        {
            if (Array.IndexOf(arrEditButton, mControl.Name.Substring(3)) >= 0)
            {
                mControl.Enabled = (sState == DataInputState.ViewMode);
            }
            else if (Array.IndexOf(arrSaveButton, mControl.Name.Substring(3)) >= 0)
            {
                mControl.Enabled = !(sState == DataInputState.ViewMode);
            }
        }
    }

    /// <summary>
    /// Set Button có style khác biệt, thường dùng trong cảnh báo, có gì thay đổi, bất thường
    /// </summary>
    /// <param name="objControl"></param>
    public static void Button_SetWarning(Control objControl)
    {
        Button_SetWarning(objControl, true);
    }

    public static void Button_SetWarning(Control objControl, bool bWarning)
    {
        if (bWarning)
        {
            Control_SetStyle(objControl, CS_STYLE_WARNING, true);
        }
        else
        {
            Control_SetStyle(objControl, CS_STYLE_CMD, true);
        }
    }

    public static void Button_SetWarning(bool bWarning, params Control[] arrControl)
    {
        foreach (Control objControl in arrControl)
        {
            Button_SetWarning(objControl, bWarning);
        }
    }

    /// <summary>
    /// Kiểm tra xem control có bắt buộc nhập liệu ko
    /// </summary>
    /// <param name="mControl"></param>
    /// <returns></returns>
    public static bool Control_GetRequired(Control mControl)
    {
        FormControlExt objFormControl = default(FormControlExt);
        if (mControl.Tag == null)
        {
            return false;
        }
        else
        {
            if (mControl.Tag is FormControlExt)
            {
                objFormControl = (FormControlExt)mControl.Tag;
                return objFormControl.Required;
            }
            else
            {
                return false;
            }
        }
    }

    /// <summary>
    /// Đặt cho control bắt buộc phải nhập liệu
    /// </summary>
    /// <param name="arrControl"></param>
    public static void Control_SetRequired(params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetRequired(mControl, true, true);
        }
    }

    public static void Control_SetRequired(bool bSetOnOff =true, bool showIcon =true, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetRequired(mControl, true, showIcon);
        }
    }

    public static void Control_SetRequired(Control mControl, bool bSetOnOff, bool showIcon = true)
    {
        //Purpose: 
        //   Thủ tục set hoặc unset bắt buộc nhập cho 1 ô nhập liệu TextBox hoặc ComboBox
        //Parameters: 
        //   mControl : đối tượng TextBox hoặc ComboBox
        //   bSetOn   : set required On/Off        
        //Notes:
        //   Auto make require sign and on/off required field

        FormControlExt objFormControl = default(FormControlExt);
        if (mControl.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            if (mControl.Tag is FormControlExt)
            {
                objFormControl = (FormControlExt)mControl.Tag;
            }
            else
            {
                if (!bSetOnOff)
                {
                    return;
                }
                else
                {
                    objFormControl = new FormControlExt();
                    objFormControl.Tag = mControl.Tag;
                }
            }
        }

        if (mControl.Parent != null)
        {
        }
        string sLabelName = mControl.Name + "_Required";
        Control objControl = default(Control);
        if (mControl.Parent != null)
        {
            if (!mControl.Parent.Controls.IsReadOnly)
            {
                objControl = mControl.Parent.Controls[sLabelName];
            }
            else
            {
                objControl = mControl.Parent.Parent.Controls[sLabelName];
            }
        }
        if (bSetOnOff)
        {
            Control mLabel = objControl;
            if (mLabel == null)
            {
                mLabel = new TransparentLabel();
                mLabel.Name = sLabelName;
                mLabel.Text = "*";
                Control_SetStyle(mLabel, CS_STYLE_REQUIRED);
                if (mControl.Parent.Controls.IsReadOnly)
                {
                    mLabel.Top = mControl.Top + 3;
                    mLabel.Left = mControl.Left - 5;
                    mControl.Parent.Parent.Controls.Add(mLabel);
                }
                else
                {
                    mLabel.Top = mControl.Top;
                    mLabel.Left = mControl.Left - 10;
                    mControl.Parent.Controls.Add(mLabel);
                }
                mLabel.Visible = (!(mControl is CheckBox)) || showIcon;
                mLabel.BringToFront();
            }
            else
            {
                if ((objControl.Name == sLabelName & objControl.Text == "*") && showIcon)
                {
                    objControl.Visible = true;
                }
            }
            objFormControl.Required = true;
        }
        else
        {
            if ((objControl != null))
            {
                if (objControl.Name == sLabelName & objControl.Text == "*")
                {
                    objControl.Visible = false;
                }
            }
            objFormControl.Required = false;
        }
        mControl.Tag = objFormControl;
    }

    /// <summary>
    /// Lấy label text tương ứng với control
    /// </summary>
    /// <param name="mControl"></param>
    /// <returns></returns>
    public static string Control_GetLabelText(Control mControl)
    {
        //Purpose: 
        //   Hàm lấy control Label được set tab index liền ngay trước Control
        //Parameters: 
        //   mControl : đối tượng Control     
        //Notes:
        //   
        string sCaption = "";
        Control lblControl = Control_GetLabelControl(mControl);
        if ((lblControl != null))
        {
            sCaption = lblControl.Text.Replace("&", "");
        }
        //
        return sCaption;
    }

    public static Label Control_GetLabelControl(Control mControl)
    {
        //Purpose: 
        //   Hàm lấy control Label được set tab index liền ngay trước Control
        //Parameters: 
        //   mControl : đối tượng Control     
        //Notes:
        //   
        Control lblControl = mControl.Parent.GetNextControl(mControl, false);
        while ((lblControl != null))
        {
            if (lblControl is Label && lblControl.Text != "*")
            {
                break; // TODO: might not be correct. Was : Exit While
            }
            else
            {
                lblControl = lblControl.Parent.GetNextControl(lblControl, false);
            }
        }
        if ((lblControl != null) && Math.Abs(lblControl.Top - mControl.Top) > 15)
        {
            lblControl = null;
        }
        //
        return (Label)lblControl;
    }

    public static void Control_SetVisible(bool bVisible, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetVisible(mControl, bVisible);
        }
    }

    public static void Control_SetVisible(Control mControl, bool bVisible)
    {
        mControl.Visible = bVisible;
        Control lblControl = Control_GetLabelControl(mControl);
        if ((lblControl != null))
        {
            lblControl.Visible = bVisible;
        }
    }

    /// <summary>
    /// Lấy giao diện classic của window
    /// </summary>
    /// <returns></returns>
    public static string App_GetTheme()
    {
        //Function to get the current Windows XP theme.
        //Optional: You can use it to set different colors for each theme.
        RegistryKey key = default(RegistryKey);
        string s = "WindowsClassic";
        key = Registry.CurrentUser.OpenSubKey("Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager");
        if (key != null)
        {
            if ("1" == (key.GetValue("ThemeActive").ToString()))
            {
                s = (key.GetValue("ColorName")).ToString();
            }
        }
        return s;
    }

    public static Color App_GetColor(string sColor)
    {
        if (sColor.StartsWith("#"))
        {
            return ColorTranslator.FromHtml(sColor);
        }
        else
        {
            return Color.FromName(sColor);
        }
    }

    public static long App_TextWidth(string sText, System.Drawing.Font f)
    {
        return (long)App_TextSize(sText, f).Width;
    }

    public static SizeF App_TextSize(string sText, System.Drawing.Font f)
    {
        System.Drawing.Bitmap i = new System.Drawing.Bitmap(1, 1);
        System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(i);
        System.Drawing.SizeF fSize = g.MeasureString(sText, f);
        return fSize;
    }

    #endregion

    //Control Style Defined
    static internal string CS_FONT_NAME = "Tahoma";
    // Control view style
    static internal string CS_STYLE_VIEW = "#e0e0e0"; //màu nền các control view
    // Control required style
    static internal string CS_STYLE_REQUIRED = "#FF4500;Bold";
    // Control info style
    static internal string CS_STYLE_INFO = "#00008B;Bold";
    // Control label style
    static internal string CS_STYLE_LABEL = "#000000;Regular";
    // Control edit style
    static internal string CS_STYLE_INPUT = "#000000;Bold";
    // Control toolbar edit style
    static internal string CS_STYLE_TOOLBAR = "#000080;Bold;10";
    // Command button style
    static internal string CS_STYLE_CMD = "#000000;Bold";
    // Control warning style
    static internal string CS_STYLE_WARNING = "#CD2626;Bold";
    // Group Box style
    static internal string CS_STYLE_GROUP = "#000000"; //"#000000;Bold";
    //Grid alternative row background
    static internal string CS_GRID_ROW_ALTER = "#FFFFFF";//"#efefef";
    //Grid normal row background
    static internal string CS_GRID_ROW = "#ffffff";
    //Grid header cell style
    static internal string CS_GRID_HEADER = "#CC0000";
    //Grid row cell style
    static internal string CS_GRID_CELL = "#000000;Regular";
    //Message Defined
    static internal string CS_DELETE_CONFIRM = "Bạn có chắc chắn muốn xóa";
    static internal string CS_DATA_SAVING = "Đang lưu";
    static internal string CS_DATA_SAVED = "Đã lưu";
    static internal string CS_INPUT_NUMERIC = "Vui lòng nhập dữ liệu kiểu số";
    static internal string CS_INPUT_INTEGER = "Vui lòng nhập dữ liệu kiểu số nguyên dương";
    static internal string CS_INPUT_DATE = "Vui lòng nhập dữ liệu kiểu ngày tháng";
    static internal string CS_INPUT_TIME = "Please input Time value";
    static internal string CS_INPUT_EMAIL = "Please input Email address";
    static internal string CS_INPUT_WEB = "Please input Web address";
    static internal string CS_INPUT_REGEX = "Please input with pattern {0}";
    //Others Defined
    static internal Keys CS_LOOKUP_KEY = Keys.F4;
    public static int CS_IDLE_TIMEOUT = 30;
    //Current user info
    public static long CS_USER_ID = 0;
    public static string CS_USER_NAME = "";
    public static string CS_USER_FULLNAME = "";
    //Danh sach theo Role Id
    public static string CS_USER_ROLES = "";
    //Danh sach theo Role Code
    public static string CS_USER_ROLES_CODE = "";
    public static long CS_UNIT_ID = 0;
    public static long CS_UNIT_ROOT = 0;
    public static string CS_USER_UNITS = "";
    //
    public static DataRowEx HotKeyData;


    //
    //Cau truc phuc vu cho viec SetFormField va Handle Input
    /// <summary>
    /// Class phục vụ cho setform field tự động theo database
    /// </summary>
    public struct FormControlExt
    {
        public bool Required;
        public string FieldName;
        public string DataFormat;
        public byte DataScale;
        public object HandleObject;
        public Control HandleControl;
        public object Tag;
        public object InitValue;
        public object PrevValue;
        public bool Lookup;
        //
        public EventHandler DefaultHandle;
        public Button DefaultButton;
    }

    /// <summary>
    /// Các loại control nhập liệu trên form
    /// </summary>
    private static string[] cs_Control_Input = new string[] {
		"TextBox",
        //"MaskedTextBox", //--hiepdh
		"ComboBox",
		"CheckBox",
		"RichTextBox",
		"RadioButtonList",
		"CheckedListBox"
	};
    private static string[] cs_Control_Toolbar = new string[] {
		"ToolStripTextBoxControl",
		"ToolStripComboBoxControl"

	};



    /// <summary>
    /// Hiển thị form dialog, init các thuộc tính, sự kiện chung
    /// </summary>
    /// <param name="f"></param>
    internal static void Form_InitDialog(FormBase f)
    {
        f.BackColor = SystemColors.Control;
        f.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
        //
        f.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
        //FormStartPosition.CenterParent
        f.ShowInTaskbar = false;
        f.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
        f.MinimizeBox = false;
        f.MaximizeBox = false;
        //Apply control style
        Control_SetStyle(f);
        //Handle enter key and focus to next control
        f.KeyPreview = true;
        f.KeyDown += Dialog_KeyDown;
        //'
    }

    /// <summary>
    /// Bắt sự kiện bấm nút trên form Dialog
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public static void Dialog_KeyDown(System.Object sender, System.Windows.Forms.KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)
        {
            Control controlObj = null;
            if(sender is Form)
                controlObj = ((System.Windows.Forms.Form)sender).ActiveControl;
            else if(sender is Control)
                controlObj = ((System.Windows.Forms.Control)sender).FindForm().ActiveControl;

            string controlType = controlObj.GetType().Name;
            if ("TextBox,ComboBox,RadioButton,CheckBox".Contains(controlType))
            {
                //Nếu các control có sự kiện keydown của riêng nó, 
                if (controlType == "TextBox" && ((TextBox)controlObj).Multiline)
                    return;

                //Focus tới control tiếp theo
                if (((System.Windows.Forms.Form)sender).SelectNextControl(((System.Windows.Forms.Form)sender).ActiveControl, true, true, true, true))
                {
                    //
                    if (((System.Windows.Forms.Form)sender).ActiveControl is TextBox)
                    {
                        (((System.Windows.Forms.Form)sender).ActiveControl as TextBox).SelectAll();
                    }
                }

                //Cái này để hủy sự kiện phát sinh từ các control con
                

                e.Handled = true;
                e.SuppressKeyPress = true; //bỏ tiếng kêu DING
            }
        }
    }

    /// <summary>
    /// Form bắt đầu khởi tạo
    /// </summary>
    /// <param name="objForm"></param>
    /// <param name="KeepProperty"></param>
    public static void Form_BeginInit(ref System.Windows.Forms.Form objForm, bool KeepProperty = false)
    {
        var _with1 = objForm;
        if (KeepProperty)
        {
            FormProperty p = new FormProperty();
            p.ControlBox = _with1.ControlBox;
            p.FormBorderStyle = _with1.FormBorderStyle;
            p.Location = _with1.Location;
            p.ShowIcon = _with1.ShowIcon;
            p.ShowInTaskbar = _with1.ShowInTaskbar;
            p.Size = _with1.Size;
            p.StartPosition = _with1.StartPosition;
            _with1.Tag = p;
        }
        objForm.ControlBox = false;
        objForm.ShowIcon = false;
        objForm.ShowInTaskbar = false;
        objForm.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        objForm.WindowState = System.Windows.Forms.FormWindowState.Normal;
        objForm.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width, Screen.PrimaryScreen.WorkingArea.Height);
        objForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
        objForm.Show();
    }

    /// <summary>
    /// Form đã khởi tạo xong
    /// </summary>
    /// <param name="objForm"></param>
    public static void Form_EndInit(System.Windows.Forms.Form objForm)
    {
        objForm.Hide();
        if (objForm.Tag is FormProperty)
        {
            FormProperty p = (FormProperty)objForm.Tag;
            var _with2 = objForm;
            _with2.ControlBox = p.ControlBox;
            _with2.FormBorderStyle = p.FormBorderStyle;
            _with2.ShowIcon = p.ShowIcon;
            _with2.ShowInTaskbar = p.ShowInTaskbar;
            _with2.Size = p.Size;
            if (p.StartPosition == System.Windows.Forms.FormStartPosition.Manual)
            {
                _with2.Location = p.Location;
            }
            else
            {
                _with2.Location = Point.Empty;
            }
            _with2.StartPosition = p.StartPosition;
        }
    }

    public static void Form_SetText(System.Windows.Forms.Form f, DataInputState mDataInputState)
    {
        Form_SetText(f, f.Text, mDataInputState, "");
    }

    //As String
    public static void Form_SetText(System.Windows.Forms.Form f, string sFunctionName, DataInputState mDataInputState = DataInputState.BrowseMode, string sDescText = "")
    {
        //Purpose: 
        //   Set caption text cho form show in tab
        //Parameters: 
        //   sFunctionName : tên chức năng
        //   mDataInputState: trạng thái nhập liệu (trường hợp form Browse sẽ = Nothing) 
        //   sDescText : ghi chú (thường là mã hoặc tên của đối tượng, nếu AddNew thì để trống)
        //Notes
        //               
        string sReturn = null;
        sReturn = sFunctionName.Trim() + " - ";

        switch (mDataInputState)
        {
            case DataInputState.BrowseMode:
                sReturn += "[Browse]";
                break;
            case DataInputState.AddMode:
                sReturn += "[New";
                break;
            case DataInputState.EditMode:
                sReturn += "[Edit";
                break;
            case DataInputState.ViewMode:
                sReturn += "[View";
                break;
            case DataInputState.CopyMode:
                sReturn += "[Copy";
                break;
            case DataInputState.VersionMode:
                sReturn += "[New Version";
                break;
            case DataInputState.ReviewMode:
                sReturn += "[Review";
                break;
            case DataInputState.ApproveMode:
                sReturn += "[Approve";
                break;
        }
        if (mDataInputState != DataInputState.BrowseMode)
        {
            if (sDescText.Length > 0)
            {
                sReturn += " - " + sDescText.Trim() + "]";
            }
            else
            {
                sReturn += "]";
            }
        }
        f.Text = sReturn;
    }

    /// <summary>
    /// Quá trình lưu dữ liệu, có transaction, hiển thị biểu tượng quay, thể hiện đang lưu dữ liệu
    /// </summary>
    /// <param name="_MethodAddress"></param>
    /// <param name="messageDoing"></param>
    /// <param name="messageDone"></param>
    public static void App_ProgressSave(MethodInvoker _MethodAddress, string messageDoing, string messageDone)
    {
        string sTrans = "";
        bool hasTrans = DataConnect.Check_Trans(ref sTrans);
        if (!hasTrans)
            DataConnect.Begin_Trans();
        try
        {
            App_ProgressShow(_MethodAddress, messageDoing, messageDone);
            if (!hasTrans)
                DataConnect.Commit_Trans();
        }
        catch
        {
            if (!hasTrans)
                DataConnect.Rollback_Trans();
            throw;
        }
    }

    /// <summary>
    /// Lấy form đang active
    /// </summary>
    /// <returns></returns>
    public static Form GetActiveForm()
    {
        // Returns null for an MDI app
        Form activeForm = Form.ActiveForm;
        if (activeForm == null)
        {
            FormCollection openForms = Application.OpenForms;
            for (int i = 0; i < openForms.Count && activeForm == null; ++i)
            {
                Form openForm = openForms[i];
                if (openForm.IsMdiContainer)
                {
                    activeForm = openForm.ActiveMdiChild;
                }
            }
        }

        return activeForm;
    }


    public static void App_ProgressSave(MethodInvoker _MethodAddress, string messageDoing)
    {
        App_ProgressSave(_MethodAddress, messageDoing, "");
    }

    public static void App_ProgressSave(MethodInvoker _MethodAddress)
    {
        App_ProgressSave(_MethodAddress, CS_DATA_SAVING, CS_DATA_SAVED);
    }

    /// <summary>
    /// Hiển thị biểu tượng quay, đang tải dữ liệu, hoặc đang thực hiện
    /// </summary>
    /// <param name="_MethodAddress"></param>
    public static void App_ProgressShow(MethodInvoker _MethodAddress)
    {
        frmProgress.Instance().Thread = _MethodAddress;
        frmProgress.Instance().Show_Progress();
    }

    public static void App_ProgressShow(MethodInvoker _MethodAddress, string sInitText)
    {
        frmProgress.Instance().Thread = _MethodAddress;
        frmProgress.Instance().Show_Progress(sInitText);
    }

    public static void App_ProgressShow(MethodInvoker _MethodAddress, string sInitText, string sFinishText)
    {
        frmProgress.Instance().Thread = _MethodAddress;
        frmProgress.Instance().Show_Progress(sInitText, sFinishText);
    }

    public static void App_ProgressShow(SubInvoker _SubAddress, object objInput, string sInitText)
    {
        frmProgress.Instance().ThreadSub = _SubAddress;
        frmProgress.Instance().ThreadInputObject = objInput;
        frmProgress.Instance().Show_Progress(sInitText);
    }

    public static object App_ProgressShow(FunctionInvoker _FunctionAddress, object objInput, string sDesc)
    {
        frmProgress.Instance().ThreadFunction = _FunctionAddress;
        frmProgress.Instance().ThreadInputObject = objInput;
        return frmProgress.Instance().Show_Progress(sDesc);
    }

    public static void App_ProgressText(string descText)
    {
        frmProgress.Instance().SetDescriptionText(descText);
    }

    public static void App_ProgressPause()
    {
        frmProgress.Instance().SetVisible(false);
    }

    public static void App_ProgressResume()
    {
        frmProgress.Instance().SetVisible(false);
    }

    //------Các hàm thông báo message---------------------
    //----------------------------------------------------
    #region Các hàm thông báo Message


    public static void Message_Error(Exception ex, string sDesc)
    {
        //Thủ tục hiện Error message 
        //Có thể hỗ trợ ghi lại lỗi hoặc translate lỗi thành message thân thiện hơn
        //will comming soon ...
        string sMessage = ex.Message;
        //Hỗ trợ hiển thị message từ việc raise lỗi trong database
        if (sMessage.Contains("[MSG]"))
        {
            sMessage = sMessage.Substring(sMessage.IndexOf("[MSG]") + "[MSG]".Length);
            if (sMessage.Contains("[/MSG]"))
                sMessage = sMessage.Substring(0, sMessage.IndexOf("[/MSG]")).Trim();
            Message_Warning(sMessage);
            return;
        }
        if (!App_IsDebug())
        {
            sMessage = "Some errors occurred while processing the requested tasks. Please contact system administrator for more details.";
            //Insert to error log here
            try
            {
                SystemController.Instance().Error_Insert(Client_Info(), Environment_Info(), CS_USER_NAME, Function_Info(), ex);
            }
            catch (Exception ex2)
            {
                SystemController.Instance().Error_Insert("Error", ex.Message, CS_USER_NAME, Function_Info(), ex2);
            }
        }
        else
        {
            if (!string.IsNullOrEmpty(sDesc))
            {
                sMessage = "Description: " + sDesc + Globals.vbCr;
            }
            else
            {
                sMessage = "";
            }
            sMessage = ex.Message.Replace(Globals.vbCrLf, Globals.vbCr + "     ");
            sMessage += "Message: " + sMessage;
            sMessage += Globals.vbCr + "Trace: " + ex.StackTrace;
        }
        MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }


    public static bool Message_Delete(string objType)
    {
        return Message_Delete(objType, "");
    }

    public static bool Message_Delete(string objType, string sObjName)
    {
        //Hàm confirm khi xóa dữ liệu
        return Message_Confirm(CS_DELETE_CONFIRM + " " + objType + (string.IsNullOrEmpty(sObjName) ? "" : " '" + sObjName + "'"));
    }

    public static bool Message_Confirm(string sMessage)
    {
        return Message_Confirm(sMessage, false);
    }

    public static bool Message_Confirm(string sMessage, bool bShowRetry)
    {
        if (!sMessage.Trim().EndsWith("?") && !sMessage.Trim().EndsWith("."))
            sMessage += "?";
        //Hàm hiện message confirm 
        if (bShowRetry)
        {
            return (MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.RetryCancel, MessageBoxIcon.Question) == DialogResult.Retry);
        }
        else
        {
            return (MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes);
        }
    }

    public static DialogResult Message_YesNoCancel(string sMessage)
    {
        //Hàm hiện message YesNoCancel
        return MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
    }

    public static void Message_Information(string sMessage)
    {
        //Thủ tục hiện message information
        MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    public static void Message_Warning(string sMessage)
    {
        //Thủ tục hiện message warning
        MessageBox.Show(sMessage, Globals.Application_GetTitle(), MessageBoxButtons.OK, MessageBoxIcon.Warning);
    }

    public static void Message_Error(Exception ex)
    {
        Message_Error(ex, "");
    }
    #endregion
    //------Các hàm thông báo message---------------------
    //----------------------------------------------------

    /// <summary>
    /// Thông tin về mạng của máy client
    /// </summary>
    /// <returns></returns>
    private static string Client_Info()
    {
        string retVal = "";
        System.Net.NetworkInformation.NetworkInterface[] nics = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces();
        foreach (System.Net.NetworkInformation.NetworkInterface nic in nics)
        {
            if (retVal.Length > 0)
                retVal += ";";
            retVal += nic.GetPhysicalAddress().ToString();
        }
        return Environment.MachineName + "(" + retVal + ")";
    }

    /// <summary>
    /// Thông tin về môi trường máy của client
    /// </summary>
    /// <returns></returns>
    private static string Environment_Info()
    {
        string retVal = null;
        retVal = string.Format("OS Version: {0}; OS User: {1}", Environment.OSVersion, Environment.UserName);
        return retVal;
    }

    private static string Function_Info()
    {
        string retVal = "";
        int iCount = Application.OpenForms.Count;
        if (iCount > 0)
        {
            Form activeForm = Application.OpenForms[iCount - 1];
            if (activeForm.IsMdiChild)
                activeForm = Application.OpenForms[0].ActiveMdiChild;
            retVal += string.Format("Form: {0} ({1})", activeForm.Name, activeForm.Text);
            if (activeForm.ActiveControl != null)
            {
                retVal += string.Format(";Control: {0} ({1})", activeForm.ActiveControl.Name, activeForm.ActiveControl.Text);
            }
        }
        return retVal;
    }
     
    /// <summary>
    /// Chương trình chạy test chế độ Debug hay không
    /// </summary>
    /// <returns></returns>
    public static bool App_IsDebug()
    {
        return (Globals.Object_GetValue<bool>(Globals.Application_GetConfig("IsDebug")) || Debugger.IsAttached);
    }

    public object Combo_GetValue(ToolStripComboBox objCombo)
    {
        return Combo_GetValue(objCombo.ComboBox);
    }

    public static object Combo_GetValue(ComboBox objCombo)
    {
        //Purpose: 
        //   Hàm lấy giá trị select của combo
        //Parameters: 
        //   objCombo    : đối tượng combobox
        //Notes


        if ((objCombo.SelectedValue != null))
        {
            //Detech null item
            if (objCombo.DisplayMember == objCombo.ValueMember && objCombo.SelectedIndex == 0 && (Globals.DB_GetString(objCombo.SelectedValue) == COMBO_ITEM_SELECT_ALL || Globals.DB_GetString(objCombo.SelectedValue) == COMBO_ITEM_BLANK))
            {
                return null;
            }
            else
            {
                return objCombo.SelectedValue;
            }
        }
        else if ((objCombo.SelectedItem != null))
        {
            object objItem = objCombo.Items[objCombo.SelectedIndex];
            if (!string.IsNullOrEmpty(objCombo.ValueMember))
            {
                Type objType = objItem.GetType();
                PropertyInfo objProperty = Globals.Object_GetProperty(objType, objCombo.ValueMember);
                if (objProperty == null)
                {
                    return objItem;
                }
                else
                {
                    return objProperty.GetValue(objItem, null);
                }
            }
            else
            {
                return objItem;
            }
        }
        else
        {
            return Null.NullString;
            //COMBO_ITEM_NULL_VALUE
        }
    }


    //---------Setform field

    //-------------------------------------
    //Luu lai ket qua SetFormField de reuse
    //-------------------------------------
    static Dictionary<string, List<FormField>> mFieldCache = new Dictionary<string, List<FormField>>();
    static Dictionary<string, DataTable> mTableCache = new Dictionary<string, DataTable>();
    //
    
    /// <summary>
    /// Tìm control từ control cha theo tên
    /// </summary>
    /// <param name="mParentControl"></param>
    /// <param name="sName"></param>
    /// <returns></returns>
    public static object Find_Control(Control mParentControl, string sName)
    {
        if (mParentControl.Controls.ContainsKey(sName))
        {
            return mParentControl.Controls[sName];
        }
        else
        {
            Control[] arrControl = mParentControl.Controls.Find(sName, true);
            if (arrControl.Length == 0)
                return null;
            return arrControl[0];
        }
    }
    //
    private static List<FormField> FormField_GetCache(Control objControl, string sTableName)
    {
        string sKey = ControlField_GetKey(objControl, sTableName);
        if (!mFieldCache.ContainsKey(sKey))
        {
            return null;
        }
        else
        {
            return mFieldCache[sKey];
        }
    }

    /// <summary>
    /// Lấy danh sách các cột của table trong Database 
    /// </summary>
    /// <param name="sTableName"></param>
    /// <returns></returns>
    private static DataTable GetTableField(string sTableName)
    {
        sTableName = sTableName.ToUpper();
        if (!mTableCache.ContainsKey(sTableName))
        {
            DataTable mDataTable = SystemController.Instance().Table_GetField(sTableName);
            mDataTable.PrimaryKey = new DataColumn[] { mDataTable.Columns["COLUMN_NAME"] };
            mDataTable.AcceptChanges();
            mTableCache.Add(sTableName, mDataTable);
        }
        return mTableCache[sTableName];
    }

    /// <summary>
    /// Gán các thuộc tính của các cột trong database lên các control trên form
    /// </summary>
    /// <param name="objControl"></param>
    /// <param name="sTableName"></param>
    /// <param name="sFieldName"></param>
    public static void Control_SetFormField(Control objControl, string sTableName, string sFieldName)
    {
        //Purpose: 
        //   Tự động đặt kiểu dữ liệu, độ dài, required cho 1 control nhập liệu theo TableName và Field Name
        //Parameters: 
        //   objControl : đối tượng chứa các ô nhập liệu
        //   sTableName : tên Table tương ứng với form nhập liệu
        //Notes:
        //   Chỉ dùng khi set cho 1 field lẻ
        DataTable mDataTable = default(DataTable);
        try
        {
            mDataTable = GetTableField(sTableName);
            DataRow dtRow = mDataTable.Rows.Find(sFieldName);
            if ((dtRow != null))
            {
                FormField mFormField = new FormField();
                mFormField.ControlType = objControl.GetType().Name;
                SetControlField(objControl, ref mFormField, dtRow);
            }
            else
            {
                throw new Exception("Field not found");
            }
        }
        catch
        {
            throw;
        }
    }

    public static void Panel_SetFormField(Control objControl, string sTableName)
    {
        Panel_SetFormField(objControl, sTableName, "");
    }

    public static void Panel_SetFormField(Control objControl, string sTableName, string sExceptControl)
    {
        //Purpose: 
        //   Tự động đặt kiểu dữ liệu, độ dài, required cho form nhập liệu theo database
        //Parameters: 
        //   objControl : đối tượng chứa các ô nhập liệu
        //   sTableName : tên Table tương ứng với form nhập liệu
        //Notes:
        //   Hỗ trợ cache DataTable

        DataTable mDataTable = default(DataTable);
        string sKey = ControlField_GetKey(objControl, sTableName);
        try
        {
            List<FormField> arrCache = default(List<FormField>);
            if (!mFieldCache.ContainsKey(sKey))
            {
                mDataTable = GetTableField(sTableName);
                if (mDataTable.Rows.Count > 0)
                {
                    arrCache = SetControlByField(objControl, mDataTable, sExceptControl);
                    mFieldCache.Add(sKey, arrCache);
                }
                else
                {
                    throw new Exception("Table '" + sTableName + "' do not exist");
                }
            }
            else
            {
                arrCache = mFieldCache[sKey];
                SetControlField(objControl, arrCache);
            }
            //Tự động gán thêm nếu có optional theo form name
            Panel_SetRequired(objControl);
            //
            objControl.Tag = sTableName;
        }
        catch
        {
            throw;
        }
        finally
        {
            //If Not mDataTable Is Nothing Then mDataTable.Dispose()
        }
    }

    public static void Panel_SetRequired(Control ctlPanel)
    {
        string sFormName = ctlPanel.FindForm().Name;
        string sRequiredField = SystemController.Instance().Domain_GetItemValue("SYS.FORM_REQUIRED", sFormName, "").ToUpper();
        string[] arrRequiredField = sRequiredField.Split(new char[] { ',' });
        //
        Panel_SetRequired(ctlPanel, arrRequiredField);
    }

    private static void Panel_SetRequired(Control ctlPanel, string[] arrRequiredField)
    {
        foreach (Control ctlInput in ctlPanel.Controls)
        {
            if (cs_Control_Input.Contains(ctlInput.GetType().Name))
            {
                if (arrRequiredField.Contains(ctlInput.Name.Substring(3).ToUpper()))
                {
                    Control_SetRequired(ctlInput);
                }
            }
            else if (ctlInput.HasChildren)
            {
                Panel_SetRequired(ctlInput, arrRequiredField);
            }
        }
    }

    public static void Panel_SetFormDefault(Control objControl, string sTableName)
    {
        DataRowEx defaultData = SystemController.Instance().Default_GetTable(sTableName);
        //Convert formula default value
        foreach (string sKey in defaultData.Data.Keys.ToArray())
        {
            switch (defaultData.Item(sKey).ToString().ToUpper())
            {
                case "=SYSDATE":
                    defaultData.Data[sKey] = SystemController.Instance().Sys_GetDate().ToString(Globals.CS_DISPLAY_DATE_FORMAT);
                    break;
                case "=SYSDATETIME":
                    defaultData.Data[sKey] = SystemController.Instance().Sys_GetDate().ToString(Globals.CS_DISPLAY_DATETIME_FORMAT);
                    break;
                case "=SYSTIME":
                    defaultData.Data[sKey] = SystemController.Instance().Sys_GetDate().ToString(Globals.CS_DISPLAY_TIME_FORMAT);
                    break;
                case "=USER_NAME":
                    defaultData.Data[sKey] = CS_USER_NAME;
                    break;
                case "=USER_FULLNAME":
                    defaultData.Data[sKey] = CS_USER_FULLNAME;
                    break;
            }
        }
        //
        Panel_FillData(objControl, defaultData);
    }

    private static void SetRequiredNote(Form objForm)
    {
        string sKey = "pnlRequired_Note";

        if (!objForm.Controls.ContainsKey(sKey))
        {
        }
    }

    //Ham Private dung de de quy SetControlByField
    private static List<FormField> SetControlByField(Control objControl, DataTable mReader, string sExcepControl)
    {
        List<FormField> arrControl = new List<FormField>();
        List<FormField> arrReturn = new List<FormField>();
        //Get arr        
        FormField mFormField2 = default(FormField);
        Control mControl2 = default(Control);

        foreach (Control mControl in objControl.Controls)
        {
            if (string.IsNullOrEmpty(mControl.Name) || sExcepControl.Contains(mControl.Name.ToUpper()))
                continue;

            if ((mControl is TextBox || mControl is ComboBox || mControl is RichTextBox || mControl is CheckBox || mControl is RadioButtonList))
            {
                mFormField2 = new FormField();
                mFormField2.ControlName = mControl.Name;
                mFormField2.FieldName = mControl.Name.Substring(3).ToUpper();
                mFormField2.ControlType = mControl.GetType().Name;
                arrControl.Add(mFormField2);
            }
            else if (mControl.Controls.Count > 0)
            {
                List<FormField> arrSub = SetControlByField(mControl, mReader, sExcepControl);
                if (arrSub.Count > 0)
                    arrReturn.AddRange(arrSub);
            }
        }

        DataRow mDataRow = default(DataRow);


        foreach (FormField mFormField in arrControl)
        {
            FormField mFormField3 = mFormField;
            mDataRow = mReader.Rows.Find(mFormField.FieldName);
            //Fix trường hợp là các field _ID hoặc _CODE
            if (mDataRow == null && mFormField.ControlType == "ComboBox")
            {
                mDataRow = mReader.Rows.Find(mFormField.FieldName + "_ID");
                if (mDataRow == null)
                {
                    mDataRow = mReader.Rows.Find(mFormField.FieldName + "_CODE");
                }
                if (mDataRow == null)
                {
                    mDataRow = mReader.Rows.Find(mFormField.FieldName + "ID");
                }
                if ((mDataRow != null))
                    mFormField3.FieldName = Globals.DB_GetString(mDataRow["COLUMN_NAME"]);
            }
            if ((mDataRow != null))
            {
                mControl2 = objControl.Controls[mFormField.ControlName];
                SetControlField(mControl2, ref mFormField3, mDataRow);
                //Lưu lại kết quả tìm được                
                arrReturn.Add(mFormField3);
            }
        }
        return arrReturn;
    }

    internal static object NumericMaxValue(ref string dataType, byte dataLen, byte dataScale)
    {
        object iMaxValue = null;
        if (dataScale > 0)
        {
            if (dataLen >= double.MaxValue.ToString().Length)
            {
                iMaxValue = double.MaxValue;
                dataType = "DOUBLE";
            }
            else if (dataLen >= decimal.MaxValue.ToString().Length)
            {
                iMaxValue = decimal.MaxValue;
                dataType = "DECIMAL";
            }
            else
            {
                iMaxValue = Math.Pow(10, (dataLen - dataScale)) - 1 / (Math.Pow(10, dataScale));
            }
        }
        else
        {
            if (dataLen > int.MaxValue.ToString().Length | dataLen == 0)
            {
                iMaxValue = long.MaxValue;
                dataType = "LONG";
            }
            else if (dataLen > short.MaxValue.ToString().Length)
            {
                iMaxValue = int.MaxValue;
                dataType = "INTEGER";
            }
            else
            {
                iMaxValue = Math.Pow(10, (dataLen)) - 1;
                dataType = "SMALLINT";
            }
        }
        return iMaxValue;
    }

    //Sử dụng cho lần chạy đầu tiên

    private static void SetControlField(Control mControl, ref FormField mFormField, DataRow mDataRow)
    {
        FormControlExt objFormControl = new FormControlExt();
        if (mFormField.ControlType == "TextBox")
        {
            string mDataType = Globals.DB_GetString(mDataRow["DATA_TYPE"]);
            object iMaxValue = null;
            if (mDataType == "NUMBER")
            {
                //If mDataRow.Item("DATA_SCALE") > 0 Then
                //    mFormField.DataScale = mDataRow.Item("DATA_SCALE")
                //    objFormControl.DataScale = mFormField.DataScale
                //    If mDataRow.Item("DATA_LENGTH") > Double.MaxValue.ToString.Length Then
                //        mDataType = "DOUBLE"
                //    End If
                //    iMaxValue = 10 ^ (mDataRow.Item("DATA_LENGTH") - mDataRow.Item("DATA_SCALE")) - 1 / (10 ^ mDataRow.Item("DATA_SCALE"))
                //Else
                //    If mDataRow.Item("DATA_LENGTH") > Integer.MaxValue.ToString.Length Or mDataRow.Item("DATA_LENGTH") = 0 Then
                //        mDataType = "LONG"
                //    ElseIf mDataRow.Item("DATA_LENGTH") > Short.MaxValue.ToString.Length Then
                //        mDataType = "INTEGER"
                //    Else
                //        mDataType = "SMALLINT"
                //        iMaxValue = 10 ^ (mDataRow.Item("DATA_LENGTH")) - 1
                //    End If
                //End If
                iMaxValue = NumericMaxValue(ref mDataType, Globals.DB_GetValue<byte>(mDataRow["DATA_LENGTH"]), Globals.DB_GetValue<byte>(mDataRow["DATA_SCALE"]));
                if (Globals.DB_GetValue<int>(mDataRow["DATA_SCALE"]) > 0)
                {
                    mFormField.DataScale = Globals.DB_GetValue<byte>(mDataRow["DATA_SCALE"]);
                    mFormField.DataFormat = "#,##0." + Globals.String_Repeat("#", mFormField.DataScale);
                    objFormControl.DataScale = mFormField.DataScale;
                    objFormControl.DataFormat = mFormField.DataFormat;
                }
            }

            TextBoxHandle txtHandle = new TextBoxHandle(mControl as TextBox, mDataType, null, iMaxValue);

            switch (Globals.DB_GetValue<String>(mDataRow["DATA_TYPE"]).ToUpper())
            {
                case "NVARCHAR2":
                case "CHAR":
                case "VARCHAR2":
                case "NCHAR":
                case "VARCHAR":
                case "NVARCHAR":
                    ((TextBox)mControl).MaxLength = Globals.DB_GetValue<int>(mDataRow["DATA_LENGTH"]);
                    break;
                case "CLOB":
                case "NCLOB":
                case "NTEXT":
                case "TEXT":
                    ((TextBox)mControl).MaxLength = Int32.MaxValue;
                    break;
                case "NUMBER":
                case "MONEY":
                case "DECIMAL":
                case "INT":
                case "NUMERIC":
                    if (((TextBox)mControl).MaxLength > Globals.DB_GetValue<int>(mDataRow["DATA_LENGTH"]))
                    {
                        ((TextBox)mControl).MaxLength = Globals.DB_GetValue<int>(mDataRow["DATA_LENGTH"]);
                    }
                    break;
            }

            objFormControl.HandleObject = txtHandle;
            //Hold cache data
            mFormField.DataType = mDataType;
            mFormField.MaxValue = iMaxValue;
            mFormField.DataLength = ((TextBox)mControl).MaxLength;
        }
        else if (mFormField.ControlType == "RichTextBox")
        {
            ((RichTextBox)mControl).MaxLength = Globals.DB_GetValue(mDataRow["DATA_LENGTH"], Int32.MaxValue);
        }
        else if (mFormField.ControlType == "ComboBox")
        {
            if (mControl.TabStop)
            {
                ComboBoxHandle cboHandle = new ComboBoxHandle(mControl as ComboBox);
                objFormControl.HandleObject = cboHandle;
            }
        }
        else if (mFormField.ControlType == "CheckBox" || mFormField.ControlType == "CheckedListBox" || mFormField.ControlType == "RadioButtonList")
        {
            //Nothing
        }
        else
        {
            throw new Exception("Not support type of control " + mFormField.ControlType);
        }
        if ((mControl.Tag != null))
        {
            //Keep current Tag value, must use GetControlTag for retrieve value
            if (mControl.Tag is FormControlExt)
            {
                objFormControl.Tag = ((FormControlExt)mControl.Tag).Tag;
            }
            else
            {
                objFormControl.Tag = mControl.Tag;
            }
        }
        objFormControl.FieldName = mFormField.FieldName;
        mControl.Tag = objFormControl;
        //Hold cache data
        mFormField.Required = (Globals.DB_GetValue<String>(mDataRow["NULLABLE"]) == "N");
        if (mFormField.Required && mControl.TabStop)
        {
            Control_SetRequired(mControl, true);
        }

    }
    //Sử dụng khi lấy lại thông tin từ Cache
    private static void SetControlField(Control mParentControl, List<FormField> arrFormField)
    {
        foreach (FormField mFormField in arrFormField)
        {
            //Dim arrControl() As Control = mParentControl.Controls.Find(mFormField.ControlName, True)
            //If arrControl.Length = 0 Then Continue For
            //Dim mControl As Control = arrControl(0)
            Control mControl = Find_Control(mParentControl, mFormField.ControlName) as Control;

            FormControlExt objFormControl = new FormControlExt();
            objFormControl.DataScale = mFormField.DataScale;
            objFormControl.DataFormat = mFormField.DataFormat;
            if (mFormField.ControlType == "TextBox")
            {
                TextBoxHandle txtHandle = new TextBoxHandle(mControl as TextBox, mFormField.DataType, null, mFormField.MaxValue);
                ((TextBox)mControl).MaxLength = mFormField.DataLength;
                objFormControl.HandleObject = txtHandle;
            }
            else if (mFormField.ControlType == "ComboBox")
            {
                ComboBoxHandle cboHandle = new ComboBoxHandle(mControl as ComboBox);
                objFormControl.HandleObject = cboHandle;
            }
            else if (mFormField.ControlType == "RichTextBox")
            {
                ((RichTextBox)mControl).MaxLength = mFormField.DataLength;
            }
            else if (mFormField.ControlType == "CheckBox" || mFormField.ControlType == "CheckedListBox" || mFormField.ControlType == "RadioButtonList")
            {
                //Do nothing
            }
            else
            {
                throw new Exception("Not support type of control " + mControl.GetType().Name);
            }
            objFormControl.FieldName = mFormField.FieldName;
            mControl.Tag = objFormControl;
            if (mFormField.ControlType != "CheckBox")
            {
                Control_SetRequired(mControl, mFormField.Required);
            }
        }
    }

    private static string ControlField_GetKey(Control objControl, string sTableName)
    {
        return objControl.FindForm().Name + "|" + objControl.Name + "|" + sTableName;
    }

    public void CheckedListBox_Init(params CheckedListBox[] ctlArray)
    {
        foreach (CheckedListBox ctl in ctlArray)
        {
            CheckedListBox_Init(ctl);
        }
    }

    //----------SetForm field


    //COmbobox
    //Các cosnt phục vụ cho item null của ComboBox
    public static string COMBO_ITEM_REQUIRE = "-- Please choose value --";
    public static string COMBO_ITEM_BLANK = "-- None --";
    public static string COMBO_ITEM_SELECT_ALL = "-- All --";
    public const string COMBO_ITEM_NULL_VALUE = "-1111111111";
    //ComboBox

    /// <summary>
    /// Lấy giá trị của control trên form
    /// </summary>
    /// <param name="mControl"></param>
    /// <returns></returns>
    internal static object Control_GetValue(Control mControl)
    {
        string sControlType = mControl.GetType().Name;
        switch (sControlType)
        {
            case "TextBox":
            case "ToolStripTextBoxControl":
                return TextBox_GetValue(mControl as TextBox);
            case "ComboBox":
            case "ToolStripComboBoxControl":
                return Combo_GetValue((ComboBox)mControl);
            //case "ToolStripComboBox":
            //    return Combo_GetValue((ToolStripComboBox)mControl);
            case "RichTextBox":
                return ((RichTextBox)mControl).Rtf;
            case "CheckBox":
                return ((CheckBox)mControl).Checked;
            //case "CheckedListBox":
            //    return CheckedListBox_GetValue(mControl);
            //case "RadioButtonList":
            //    return ((RadioButtonList)mControl).SelectedValue;
            default:
                return null;
        }
    }

    //public void CheckedListBox_Init(params CheckedListBox[] ctlArray)
    //{
    //    foreach (CheckedListBox ctl in ctlArray)
    //    {
    //        CheckedListBox_Init(ctl);
    //    }
    //}

    //, backColor As Color)
    public void CheckedListBox_Init(CheckedListBox ctl)
    {
        ctl.SelectionMode = SelectionMode.None;
        //ctl.BorderStyle = BorderStyle.None
        //ctl.BackColor = backColor 'SystemColors.Control
        ctl.Click += checkedListBox_Click;
        ctl.KeyPress += checkedListBox_KeyPress;
    }

    //Public Sub CheckedListBox_Init(ByVal ctl As CheckedListBox)
    //    CheckedListBox_Init(ctl, SystemColors.Control)
    //End Sub

    public static object[] CheckedListBox_GetValue(CheckedListBox ctl)
    {
        List<object> retVal = new List<object>();
        for (int i = 0; i <= ctl.Items.Count - 1; i++)
        {
            if (ctl.GetItemChecked(i))
            {
                retVal.Add(((DataRowView)ctl.Items[i])[(ctl as ListControl).ValueMember]);
            }
        }
        return retVal.ToArray();
    }

    //Public Function CheckedListBox_GetString(ByVal ctl As CheckedListBox) As String
    //    Return ArrayToString(CheckedListBox_GetValue(ctl))
    //End Function

    public void CheckedListBox_SetValue(CheckedListBox ctl, string arrValue)
    {
        if (!string.IsNullOrEmpty(arrValue))
        {
            CheckedListBox_SetValue(ctl, arrValue.Split(new char[] { ',' }));
        }
        else
        {
            ctl.ClearSelected();
        }
    }

    public void CheckedListBox_SetValue(CheckedListBox ctl, object[] arrValue)
    {
        for (int i = 0; i <= ctl.Items.Count - 1; i++)
        {
            ctl.SetItemChecked(i, arrValue.Contains(((DataRowView)ctl.Items[i])[(ctl as ListControl).ValueMember].ToString()));
        }
    }

    private void checkedListBox_KeyPress(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar == ' ')
        {
            CheckedListBox ctl = sender as CheckedListBox;
            if (ctl.SelectedIndex > 0)
            {
                switch (ctl.GetItemCheckState(ctl.SelectedIndex))
                {
                    case CheckState.Checked:
                        ctl.SetItemCheckState(ctl.SelectedIndex, CheckState.Unchecked);
                        break;
                    case CheckState.Indeterminate:
                    case CheckState.Unchecked:
                        ctl.SetItemCheckState(ctl.SelectedIndex, CheckState.Checked);
                        break;
                }
            }
        }
    }

    private void checkedListBox_Click(object sender, EventArgs e)
    {
        CheckedListBox ctl = sender as CheckedListBox;
        for (int i = 0; i <= ctl.Items.Count - 1; i++)
        {
            if (ctl.GetItemRectangle(i).Contains(ctl.PointToClient(Control.MousePosition)))
            {
                switch (ctl.GetItemCheckState(i))
                {
                    case CheckState.Checked:
                        ctl.SetItemCheckState(i, CheckState.Unchecked);
                        break;
                    case CheckState.Indeterminate:
                    case CheckState.Unchecked:
                        ctl.SetItemCheckState(i, CheckState.Checked);
                        break;
                }
                break; // TODO: might not be correct. Was : Exit For
            }
        }
    }


    public static object Control_GetValue(Control mControl, string sDataType)
    {
        object oValue = Control_GetValue(mControl);
        return Globals.Object_SetValueEx(oValue, sDataType, false);
    }

    public static T Control_GetValue<T>(Control mControl, T nullValue)
    {
        T objReturn = Control_GetValue<T>(mControl);
        if (Null.IsNull(objReturn))
        {
            objReturn = nullValue;
        }
        return objReturn;
    }

    public static T Control_GetValue<T>(Control mControl)
    {
        T objReturn = default(T);
        object oValue = Control_GetValue(mControl);
        if (oValue == null || Null.IsNull(oValue))
        {
            return (T)Null.SetNullValue(objReturn);
        }
        else
        {
            if ((objReturn == null))
            {
                return (T)Globals.Object_SetValueEx(oValue, "String", false);
            }
            else
            {
                return (T)Globals.Object_SetValueEx(oValue, objReturn.GetType().Name, false);
            }
        }
    }

    /// <summary>
    /// Lấy lỗi của các control trên form
    /// </summary>
    /// <param name="f"></param>
    /// <returns></returns>
    public static ErrorProvider Form_GetErrorProvider(Form f)
    {
        Control ctlDummy = f.Controls[f.Name + "_ErrorProvider"];
        ErrorProvider objErrorProvider = default(ErrorProvider);
        if (ctlDummy == null)
        {
            ctlDummy = new Control();
            ctlDummy.Name = f.Name + "_ErrorProvider";
            f.Controls.Add(ctlDummy);
            objErrorProvider = new ErrorProvider();
            ctlDummy.Tag = objErrorProvider;
        }
        else
        {
            objErrorProvider = ctlDummy.Tag as ErrorProvider;
        }
        return objErrorProvider;
    }
    /// <summary>
    /// Set error cho control, khi control set error, sẽ bao gồm icon báo lỗi
    /// </summary>
    /// <param name="sError"></param>
    /// <param name="arrControl"></param>
    public static void Control_SetError(string sError, params Control[] arrControl)
    {
        foreach (Control objControl in arrControl)
        {
            Control_SetError(objControl, sError);
        }
    }

    public static void Control_SetError(Control objControl, string sError)
    {
        ErrorProvider errPro = default(ErrorProvider);
        errPro = Form_GetErrorProvider(objControl.FindForm());
        errPro.SetError(objControl, sError);
        if (!string.IsNullOrEmpty(sError))
        {
            Control objErrControl = objControl.Parent.GetChildAtPoint(new Point(objControl.Left - 18, objControl.Top));
            int iPadding = 2;
            if ((objErrControl != null) && objErrControl is TextBox)
            {
                if (((TextBox)objErrControl).ReadOnly)
                    iPadding += objControl.Left - objErrControl.Left;
            }
            errPro.SetIconAlignment(objControl, ErrorIconAlignment.TopLeft);
            errPro.SetIconPadding(objControl, iPadding);

            System.Windows.Forms.Form mForm = objControl.FindForm();
            if (mForm.AutoValidate != AutoValidate.EnableAllowFocusChange)
                mForm.AutoValidate = AutoValidate.EnableAllowFocusChange;
        }
    }

    public static string Control_GetError(Control objControl)
    {
        ErrorProvider errPro = default(ErrorProvider);
        errPro = Form_GetErrorProvider(objControl.FindForm());
        return errPro.GetError(objControl);
    }


    public static bool Panel_CheckError(Control objControl)
    {
        return Panel_CheckError(objControl, false);
    }


    //---------------------------------Handle cho textbox--------------------------------------
    //-----------------------------------------------------------------------------------------
    #region textboxhandle

    //Tự động gợi ý khi gõ vào textbox
    //-Nhược điểm chỉ gợi ý khi nhập đúng chữ cái đầu tiên, ko search like % được
    public static void TextBox_SetAutocomplete(TextBox tb, DataTable dtSource, string sColKey)
    {
        AutoCompleteStringCollection source = new AutoCompleteStringCollection();
        foreach (DataRow dr in dtSource.Rows)
        {
            source.Add(Globals.DB_GetString(dr[sColKey]));
        }
        //
        tb.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
        tb.AutoCompleteCustomSource = source;
        tb.AutoCompleteSource = AutoCompleteSource.CustomSource;
    }

    //Set water mark cho textbox: chữ lồng trong ô nhập, khi focus vào sẽ mất đi
    /// <summary>
    /// Set watermark cho textbox
    /// </summary>
    public static void TextBox_SetWaterMark(string sWaterMark,int iPadding = 2, params TextBox[] arrayTextBox)
    {
        TextBox_SetWaterMark(sWaterMark, false, iPadding, arrayTextBox);
    }

    /// <summary>
    /// Set watermark cho textbox, nếu đặt alwaysDisplay => watermark sẽ luôn hiển thị
    /// </summary>
    public static void TextBox_SetWaterMark(string sWaterMark, bool alwaysDisplay, int iPadding = 2, params TextBox[] arrayTextBox)
    {
        foreach (TextBox tb in arrayTextBox)
        {
            WaterMarkTextBox_Handle handle = new WaterMarkTextBox_Handle(tb, alwaysDisplay);
            handle.WaterMark = sWaterMark;
            handle.WaterMarkAlwaysDisplay = alwaysDisplay;
            handle.WaterMarkPadding = iPadding;
        }
    }
    
    /// <summary>
    /// Dùng trong Init_Control, gán kiểu giá trị nhập cho textbox...
    /// </summary>
    /// <param name="eDataType"></param>
    /// <param name="arrayTextBox"></param>
    public static void TextBox_SetHandle(DataInputType eDataType, params TextBox[] arrayTextBox)
    {
        foreach (TextBox tb in arrayTextBox)
        {
            TextBox_SetHandle(tb, eDataType);
        }
    }

    public static void TextBox_SetHandle(TextBox tb, DataInputType eDataType)
    {
        TextBox_SetHandle(tb, eDataType, true);
    }

    public static void TextBox_SetHandle(TextBox tb, string DataType)
    {
        TextBox_SetHandle(tb, DataType, true);
    }

    public static void TextBox_SetHandle(TextBox tb, DataInputType eDataType, bool AutoClearError)
    {
        TextBox_SetHandle(tb, eDataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tb, string DataType, bool AutoClearError)
    {
        TextBox_SetHandle(tb, DataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, DataInputType eDataType)
    {
        TextBox_SetHandle(tbMin, tbMax, eDataType, null, null, true);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, DataInputType eDataType, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, tbMax, eDataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, string DataType, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, tbMax, DataType, null, null, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, DataInputType eDataType, object MinValue, object MaxValue, bool AutoClearError)
    {
        TextBox_SetHandle(tbMin, eDataType, MinValue, tbMax, AutoClearError);
        TextBox_SetHandle(tbMax, eDataType, tbMin, MaxValue, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tbMin, TextBox tbMax, string DataType, object MinValue = null, object MaxValue = null, bool AutoClearError = false)
    {
        TextBox_SetHandle(tbMin, DataType, MinValue, tbMax, AutoClearError);
        TextBox_SetHandle(tbMax, DataType, tbMin, MaxValue, AutoClearError);
    }

    public static void TextBox_SetHandle(TextBox tb, DataInputType eDataType, object MinValue, object MaxValue, bool AutoClearError = false)
    {
        string dataType = TextBox_GetDataType(eDataType);
        TextBox_SetHandle(tb, dataType, MinValue, MaxValue, AutoClearError);
    }

    private static string TextBox_GetDataType(DataInputType eDataType)
    {
        string dataType = Globals.Enum_GetName(eDataType);
        dataType = dataType.ToUpper().Substring(0, dataType.Length - 4);
        return dataType;
    }

    public static void TextBox_SetPattern(TextBox tb, string inputPattern)
    {
        TextBox_SetPattern(tb, inputPattern, true);
    }

    /// <summary>
    /// Set textbox nhập theo RegEx, check theo RegEx
    /// </summary>
    /// <param name="tb"></param>
    /// <param name="inputPattern"></param>
    /// <param name="AutoClearError"></param>
    public static void TextBox_SetPattern(TextBox tb, string inputPattern, bool AutoClearError)
    {
        FormControlExt objFormControl = default(FormControlExt);
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            objFormControl = (FormControlExt)tb.Tag;
        }
        if (objFormControl.HandleObject == null)
        {
            objFormControl.HandleObject = new TextBoxHandle(tb, Globals.Enum_GetName(DataInputType.RegExData));
        }
        ((TextBoxHandle)objFormControl.HandleObject).InputPattern = inputPattern;
        ((TextBoxHandle)objFormControl.HandleObject).AutoClearError = AutoClearError;
        ((TextBoxHandle)objFormControl.HandleObject).DataType = TextBox_GetDataType(DataInputType.RegExData);
        tb.Tag = objFormControl;
    }

    //Handle Input cho TextBox
    public static void TextBox_SetHandle(TextBox tb, string DataType, object MinValue, object MaxValue, bool AutoClearError = false)
    {
        //Purpose: 
        //   Handle cho TextBox
        //Parameters: 
        //   tb         : đối tượng TextBox
        //   DataType   : loại dữ liệu
        //   MinValue   : giá trị nhỏ nhất
        //   MaxValue   : giá trị lớn nhất
        //Notes
        FormControlExt objFormControl = default(FormControlExt);
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        else
        {
            objFormControl = (FormControlExt)tb.Tag;
        }
        if (objFormControl.HandleObject == null)
        {
            TextBoxHandle mHandle = new TextBoxHandle(tb, DataType, MinValue, MaxValue);
            mHandle.AutoClearError = AutoClearError;
            objFormControl.HandleObject = mHandle;
        }
        else
        {
            if ((MinValue != null))
                ((TextBoxHandle)objFormControl.HandleObject).MinValue = MinValue;
            if ((MaxValue != null))
                ((TextBoxHandle)objFormControl.HandleObject).MaxValue = MaxValue;
            ((TextBoxHandle)objFormControl.HandleObject).DataType = DataType;
            //
        }
        if (DataType == "TIME")
            objFormControl.DataFormat = Globals.CS_DISPLAY_TIME_FORMAT;
        tb.Tag = objFormControl;
    }

    public static TextBoxHandle TextBox_GetHandle(TextBox tb)
    {
        TextBoxHandle mHandle = null;
        if (tb.Tag is FormControlExt)
        {
            mHandle = ((FormControlExt)tb.Tag).HandleObject as TextBoxHandle;
        }
        return mHandle;
    }

    public static string TextBox_GetFormat(TextBox tb)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if ((tb.Tag != null))
        {
            return objFormControl.DataFormat;
        }
        else
        {
            return null;
        }
    }

    public static void TextBox_SetFormat(string sFormat, params TextBox[] arrTextBox)
    {
        foreach (TextBox tb in arrTextBox)
        {
            TextBox_SetFormat(tb, sFormat);
        }
    }

    public static void TextBox_SetCase(CharacterCasing charCase, params TextBox[] arrTextBox)
    {
        foreach (TextBox tb in arrTextBox)
        {
            tb.CharacterCasing = charCase;
        }
    }

    public static void TextBox_SetFormat(TextBox tb, string sFormat)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        objFormControl.DataFormat = sFormat;
        tb.Tag = objFormControl;
    }

    public static void TextBox_SetScale(byte dataScale, params TextBox[] arrTextBox)
    {
        foreach (TextBox tb in arrTextBox)
        {
            TextBox_SetScale(tb, dataScale);
        }
    }

    public static void TextBox_SetScale(TextBox tb, byte dataScale)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if (tb.Tag == null)
        {
            objFormControl = new FormControlExt();
        }
        objFormControl.DataScale = dataScale;
        tb.Tag = objFormControl;
    }

    public static byte TextBox_GetScale(TextBox tb)
    {
        FormControlExt objFormControl = (FormControlExt)tb.Tag;
        if ((tb.Tag != null))
        {
            return objFormControl.DataScale;
        }
        else
        {
            return 0;
        }
    }

    public static void TextBox_SetValue(TextBox tb, object oValue)
    {
        TextBox_SetValue(tb, oValue, true);
    }

    public static void TextBox_SetValue(object oValue, params TextBox[] txts)
    {
        foreach (TextBox tb in txts)
        {
            TextBox_SetValue(tb, oValue);
        }
    }

    public static void TextBox_SetValue(TextBox tb, object oValue, bool bOverwrite)
    {
        if (!bOverwrite && !string.IsNullOrEmpty(tb.Text))
            return;

        TextBoxHandle mHandle = default(TextBoxHandle);
        string sText = Globals.Object_GetDisplayValue(oValue);
        if (tb.Tag == null || tb.Tag.GetType() != typeof(FormControlExt))
        {
            tb.Text = sText;
        }
        else
        {
            FormControlExt objFormControl = (FormControlExt)tb.Tag;
            //
            mHandle = (TextBoxHandle)objFormControl.HandleObject;
            if (objFormControl.Lookup)
            {
                mHandle.LookupValue = oValue;
            }
            else
            {
                if (!Null.IsNull(oValue) && !string.IsNullOrEmpty(objFormControl.DataFormat))
                {
                    if (oValue is System.DateTime)
                    {
                        tb.Text = ((System.DateTime)oValue).ToString(objFormControl.DataFormat);
                        //IsNumeric(oValue) Then
                    }
                    else if (oValue != null && Globals.Type_IsNumeric(oValue.GetType()))
                    {
                        tb.Text = Globals.Object_GetValue<decimal>(oValue).ToString(objFormControl.DataFormat);
                    }
                    else
                    {
                        tb.Text = sText;
                    }
                }
                else
                {
                    tb.Text = sText;
                }
            }
        }
    }

    public static object TextBox_GetValue(TextBox tb)
    {
        TextBoxHandle mHandle = default(TextBoxHandle);
        if (tb.Tag == null || tb.Tag.GetType() != typeof(FormGlobals.FormControlExt) || ((FormGlobals.FormControlExt)((FormGlobals.FormControlExt)tb.Tag)).HandleObject == null)
        {
            return tb.Text;
        }
        else
        {
            FormGlobals.FormControlExt objFormControl = (FormGlobals.FormControlExt)tb.Tag;
            mHandle = objFormControl.HandleObject as TextBoxHandle;
            if (objFormControl.Lookup)
            {
                return mHandle.LookupValue;
            }
            else
            {
                return Globals.Object_SetValueEx(tb.Text, mHandle.DataType);
            }
        }
    }

    //---------------------------------Handle cho textbox--------------------------------------
    //-----------------------------------------------------------------------------------------

    #endregion



    #region handle cho panel

    //----------------------------------------handle cho panel-------------------------------------
    //--------------------------------------------------------------------------------------------

    /// <summary>
    /// Lấy giá trị của đối tượng, gán lên panel, xxx + tên thuộc tính của object = tên control
    /// </summary>
    /// <param name="ctlPanel"></param>
    /// <param name="objInfo"></param>
    public static void Panel_FillData(Control ctlPanel, Standard_Info objInfo)
    {
        Panel_FillData(ctlPanel, objInfo, null);
    }

    public static void Panel_FillData(Control ctlPanel, Standard_Info objInfo, FormatInvoker customFormat)
    {
        Type objType = objInfo.GetType();
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (cs_Control_Input.Contains(sControlType))
            {
                PropertyInfo objProperty = Globals.Object_GetProperty(objType, mControl.Name.Substring(3));
                if (objProperty == null)
                    continue;
                object oValue = objProperty.GetValue(objInfo, null);
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref oValue);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Panel_FillData(mControl, objInfo);
            }
        }
    }

    public static void Panel_FillData(Standard_Info objInfo, params Control[] arrControl)
    {
        Type objType = objInfo.GetType();
        foreach (Control mControl in arrControl)
        {
            string sControlType = mControl.GetType().Name;
            if (cs_Control_Input.Contains(sControlType))
            {
                PropertyInfo objProperty = Globals.Object_GetProperty(objType, mControl.Name.Substring(3));
                if (objProperty == null)
                    continue;
                object oValue = objProperty.GetValue(objInfo, null);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Panel_FillData(mControl, objInfo);
            }
        }
    }

    public static void Panel_GetData(Standard_Info objInfo, params Control[] arrPanel)
    {
        foreach (Control ctlPanel in arrPanel)
        {
            Panel_GetData(ctlPanel, objInfo);
        }
    }

    public static void Panel_GetData(Control ctlPanel, Standard_Info objInfo)
    {
        Panel_GetData(ctlPanel, objInfo, null);
    }

    public static void Panel_GetData(Control ctlPanel, Standard_Info objInfo, FormatInvoker customFormat)
    {
        Type objType = objInfo.GetType();
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (cs_Control_Input.Contains(sControlType))
            {
                PropertyInfo objProperty = Globals.Object_GetProperty(objType, mControl.Name.Substring(3));
                if (objProperty == null)
                    continue;
                object objValue = Control_GetValue(mControl);
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref objValue);
                objValue = Globals.Object_SetValueEx(objValue, objProperty.PropertyType.Name);
                objProperty.SetValue(objInfo, objValue, null);
            }
            else if ("Panel;GroupBox".Split(new char[] { ';' }).Contains(sControlType))
            {
                Panel_GetData(mControl, objInfo);
            }
        }
    }

    public static void Panel_FillData(Control ctlPanel, DataRow objRow)
    {
        Panel_FillData(ctlPanel, objRow, null);
    }

    public static void Panel_FillData(Control ctlPanel, DataRow objRow, FormatInvoker customFormat)
    {
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (cs_Control_Input.Contains(sControlType))
            {
                if (!objRow.Table.Columns.Contains(mControl.Name.Substring(3)))
                    continue;
                object oValue = Globals.DB_GetValue(objRow[mControl.Name.Substring(3)], null);
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref oValue);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Panel_FillData(mControl, objRow);
            }
        }
    }

    public static void Panel_FillData(DataRowEx objRowEx, params Control[] arrPanel)
    {
        foreach (Control ctlPanel in arrPanel)
        {
            Panel_FillData(ctlPanel, objRowEx);
        }
    }

    public static void Panel_FillData(Control ctlPanel, DataRowEx objRowEx)
    {
        Panel_FillData(ctlPanel, objRowEx, null);
    }

    public static void Panel_FillData(Control ctlPanel, DataRowEx objRowEx, FormatInvoker customFormat)
    {
        //For Each mControl As Control In ctlPanel.Controls
        //    Dim sControlType As String = TypeName(mControl)
        //    If cs_Control_Input.Split(";").Contains(sControlType) Then
        //        If Not objRowEx.HasItem(mControl.Name.Substring(3)) Then Continue For
        //        Dim oValue As Object = objRowEx.Item(mControl.Name.Substring(3))
        //        If Not customFormat Is Nothing Then customFormat.Invoke(mControl.Name.Substring(3).ToUpper, oValue)
        //        Control_SetValue(mControl, oValue)
        //    ElseIf mControl.HasChildren Then
        //        Panel_FillData(mControl, objRowEx)
        //    End If
        //Next
        Control_FillData(ctlPanel.Controls, objRowEx, customFormat);
    }

    public void Control_FillData(Control.ControlCollection arrControl, DataRowEx objRowEx)
    {
        Control_FillData(arrControl, objRowEx, null);
    }

    public static void Control_FillData(Control.ControlCollection arrControl, DataRowEx objRowEx, FormatInvoker customFormat)
    {
        Array arr = Array.CreateInstance(typeof(Control), arrControl.Count);
        arrControl.CopyTo(arr, 0);
        Control_FillData((Control[])arr, objRowEx, customFormat);
    }

    public static void Control_FillData(Control[] arrControl, DataRowEx objRowEx)
    {
        Control_FillData(arrControl, objRowEx, null);
    }

    public void Panel_GetData(Control ctlPanel, DataRow objRow)
    {
        Panel_GetData(ctlPanel, objRow, null);
    }

    public void Panel_GetData(Control ctlPanel, DataRow objRow, FormatInvoker customFormat)
    {
        object objValue = null;
        foreach (Control mControl in ctlPanel.Controls)
        {
            string sControlType = mControl.GetType().Name;
            if (cs_Control_Input.Contains(sControlType))
            {
                if (!objRow.Table.Columns.Contains(mControl.Name.Substring(3)))
                    continue;
                objValue = Control_GetValue(mControl);
                objValue = Globals.Object_SetValueEx(objValue, objRow.Table.Columns[mControl.Name.Substring(3)].DataType.Name, true);
                if (objRow.Table.Columns[mControl.Name.Substring(3)].DataType.Name == "String")
                {
                    Int32 maxLen = objRow.Table.Columns[mControl.Name.Substring(3)].MaxLength;
                    if (maxLen > 0 && objValue.ToString().Length > maxLen)
                        objValue = objValue.ToString().Substring(0, maxLen);
                }
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref objValue);
                objRow[mControl.Name.Substring(3)] = objValue;
            }
        }
    }

    public void Control_SetValueEx(object oValue, params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            Control_SetValue(mControl, oValue);
        }
    }
    
    /// <summary>
    /// Kiểm tra panel có control bị error không, dùng khi Save data
    /// </summary>
    /// <param name="objControl"></param>
    /// <param name="bSilent"></param>
    /// <returns></returns>
    public static bool Panel_CheckError(Control objControl, bool bSilent)
    {
        //Purpose: 
        //   Tự động kiểm tra dữ liệu cần phải nhập trên form
        //Parameters: 
        //   objControl : đối tượng chứa các ô nhập liệu
        //   bSilent : check Silent True/False
        //Notes:
        //   Nếu ở chế độ check Silent sẽ không hiện MessageBox
        bool bInput = true;
        Control mControl = default(Control);
        string sControlType = null;
        SortedList<int, Control> arrControl = new SortedList<int, Control>();
        //Sort control by tab index
        if (objControl.Tag is FormControlExt)
        {
            arrControl.Add(objControl.TabIndex, objControl);
        }
        else
        {
            for (int i = 0; i <= objControl.Controls.Count - 1; i++)
            {
                mControl = objControl.Controls[i];
                sControlType = mControl.GetType().Name;
                if (mControl.Controls.Count > 0 & mControl.Enabled & (sControlType.IndexOf("Panel") > -1 | sControlType.IndexOf("Tab") > -1 | sControlType.IndexOf("Group") > -1))
                {
                    arrControl.Add(mControl.TabIndex, mControl);
                }
                else
                {
                    if (mControl.Tag is FormControlExt)
                    {
                        arrControl.Add(mControl.TabIndex, mControl);
                    }
                    else
                    {
                        continue;
                    }
                }
            }
        }
        //
        bool bReturn = true;
        foreach (Control mControl2 in arrControl.Values)
        {
            if (!(mControl2.Tag is FormControlExt))
            {
                bReturn = Panel_CheckError(mControl2, bSilent);
            }
            else
            {
                bReturn = Control_CheckError(mControl2, bSilent);
            }
            if (!bReturn)
                break; // TODO: might not be correct. Was : Exit For
        }
        //
        return bReturn;
    }

    public static bool Control_CheckError(Control mControl)
    {
        return Control_CheckError(mControl, false);
    }

    //Kiểm tra lỗi của các control, bao gồm cả các control con
    public static bool Control_CheckError(Control mControl, bool bSilent)
    {
        //Ko gán tag là FormControlExt => ko check đc error
        if (mControl.Tag == null || mControl.Tag.GetType() != typeof(FormControlExt))
            return true;
        //

        string sControlType = mControl.GetType().Name;

        FormControlExt objControlExt = (FormControlExt)mControl.Tag;
        //
        bool bRequired = true;
        //Check required
        switch (sControlType)
        {
            case "TextBox":
                if (objControlExt.Required)
                {
                    bRequired = (!string.IsNullOrEmpty(mControl.Text.Trim()));
                }
                break;
            case "ComboBox":
                if (objControlExt.Required)
                {
                    bRequired = !Null.IsNull(Combo_GetValue(mControl as ComboBox));
                }
                break;
            case "RichTextBox":
                if (objControlExt.Required)
                {
                    bRequired = !string.IsNullOrEmpty(((RichTextBox)mControl).Rtf.Trim());
                }
                break;
            case "DataGridView":
                if (objControlExt.Required)
                {
                    bRequired = ((DataGridView)mControl).Rows.Count > 0 && ((DataGridView)mControl).Rows[0].IsNewRow == false;
                }
                break;
            //bReturn = bReturn AndAlso DirectCast(objControlExt.HandleObject, DataGridHandle).CheckValid(bSilent)
            case "RadioButtonList":
                if (objControlExt.Required)
                {
                    //bRequired = (((RadioButtonList)mControl).SelectedIndex >= 0);
                }
                break;
            case "CheckedListBox":
                if (objControlExt.Required)
                {
                    bRequired = CheckedListBox_GetValue((CheckedListBox)mControl).Length > 0;
                }
                break;
            default:
                if (sControlType != "CheckBox" && objControlExt.Required)
                {
                    bRequired = (!string.IsNullOrEmpty(mControl.Text.Trim()));
                }
                break;
        }
        //
        string sError = null;
        bool bError = false;
        string sCaption = null;
        //Check validation error
        if (sControlType == "TextBox" && ((TextBox)mControl).ReadOnly == false)
        {
            sError = Control_GetError(mControl);
        }
        else if (sControlType == "DataGridView")
        {
            //sError = ((DataGridHandle)objControlExt.HandleObject).CheckError();
        }
        else
        {
            sError = Control_GetError(mControl);
        }
        bError = !string.IsNullOrEmpty(sError);
        if ((!bRequired) | bError)
        {
            if (!bSilent)
            {
                //Hỗ trợ trường hợp nằm trong tabpage không active
                Control ctlParent = mControl.Parent;
                while (!(ctlParent is Form))
                {
                    if (ctlParent is TabPage)
                    {
                        if (((TabControl)ctlParent.Parent).SelectedIndex != ((TabPage)ctlParent).TabIndex)
                        {
                            //DirectCast(ctlParent.Parent, TabControl).SelectedIndex = DirectCast(ctlParent, TabPage).TabIndex
                            ((TabControl)ctlParent.Parent).SelectedTab = (TabPage)ctlParent;
                            break; // TODO: might not be correct. Was : Exit While
                        }
                    }
                    ctlParent = ctlParent.Parent;
                }
                //
                mControl.Focus();
                //
                sCaption = Control_GetLabelText(mControl);
                if (sControlType == "DataGridView")
                {
                    if (!bError && !bRequired)
                    {
                        sError = "You must input at least one row grid data";
                        if (!string.IsNullOrEmpty(sCaption))
                            sError += " for '" + sCaption + "'";
                    }
                }
                else if (sControlType == "CheckedListBox")
                {
                    if (!bError && !bRequired)
                    {
                        sError = "You must checked at least one check value";
                        if (!string.IsNullOrEmpty(sCaption))
                            sError += " for '" + sCaption + "'";
                    }
                }
                else
                {
                    if (string.IsNullOrEmpty(sCaption))
                    {
                        sCaption = "required field";
                    }
                    else
                    {
                        sCaption = "'" + sCaption + "'";
                    }
                    if (!bError && !bRequired)
                    {
                        //sCaption = "You must input value for " + sCaption
                        //sError = "You must input value for all required field (mark with * sign)";
                        sError = "Nhập đầy đủ dữ liệu tại các mục được đánh dấu '*'";
                    }
                    if (bError)
                    {
                        if (sCaption != "required field")
                        {
                            sError = sError + " for " + sCaption;
                        }
                        bRequired = false;
                    }
                }
                Message_Warning(sError);
            }
            return false;
        }
        return true;
    }

    /// <summary>
    /// Xác định xem Panel có bị thay đổi dữ liệu hay không, dùng để kiểm tra, thông báo khi thoát form chưa lưu
    /// </summary>
    /// <param name="objControl"></param>
    /// <returns></returns>
    public bool Panel_IsChanged(Control objControl)
    {
        if (!objControl.HasChildren)
        {
            throw new Exception("Panel_IsChanged not suppport control " + objControl.GetType().Name);
        }
        bool retVal = false;
        foreach (Control mControl in objControl.Controls)
        {
            if (cs_Control_Input.Contains(mControl.GetType().Name))
            {
                retVal = Control_IsChanged(mControl);
            }
            else if (mControl.HasChildren)
            {
                retVal = Panel_IsChanged(mControl);
            }
            if (retVal)
                break; // TODO: might not be correct. Was : Exit For
        }
        return retVal;
    }


    public static FormControlExt Control_GetExtension(Control mControl)
    {
        if (mControl.Tag is FormControlExt)
        {
            return (FormControlExt)mControl.Tag;
        }
        else
        {
            return new FormControlExt();
        }
    }

    public static void Control_SetExtension(Control mControl, FormControlExt ext)
    {
        if (!(mControl.Tag is FormControlExt))
        {
            ext.Tag = mControl.Tag;
        }
        else
        {
            ext.Tag = ((FormControlExt)mControl.Tag).Tag;
        }
        ext.HandleControl = mControl;
        mControl.Tag = ext;
    }
    
    /// <summary>
    /// Kiểm tra xem control có bị thay đổi data không
    /// </summary>
    /// <param name="mControl"></param>
    /// <returns></returns>
    public bool Control_IsChanged(Control mControl)
    {
        object objInit = Control_GetExtension(mControl).InitValue;
        object objValue = Control_GetValue(mControl);
        if ((objInit != null))
        {
            if (Control_GetExtension(mControl).DataFormat == Globals.CS_DISPLAY_TIME_FORMAT && objInit is DateTime)
            {
                objInit = ((DateTime)objInit).ToString(Globals.CS_DISPLAY_TIME_FORMAT);
            }
            if (objInit.GetType().Name != "String")
            {
                objValue = Globals.Object_SetValueEx(objValue, objInit.GetType().Name);
            }
            else if (objValue != null && objValue.GetType().Name != "String")
            {
                objInit = Globals.Object_SetValueEx(objInit, objValue.GetType().Name);
            }
        }
        return objValue != objInit;
    }

    /// <summary>
    /// Kiểm tra control 
    /// </summary>
    /// <param name="mControl"></param>
    /// <returns></returns>
    public bool Control_IsEditable(Control mControl)
    {
        string sControlType = mControl.GetType().Name;
        switch (sControlType)
        {
            case "TextBox":
            case "ToolStripTextBoxControl":
                return !(((TextBox)mControl).ReadOnly || !((TextBox)mControl).Enabled);
            case "RichTextBox":
                return !(((RichTextBox)mControl).ReadOnly || !((RichTextBox)mControl).Enabled);
            default:
                return mControl.Enabled;
        }
    }


    //public static void Control_SetValueEx(object oValue, params Control[] arrControl)
    //{
    //    foreach (Control mControl in arrControl)
    //    {
    //        Control_SetValue(mControl, oValue);
    //    }
    //}

    //Gán giá trị cho các control trên form
    public static void Control_SetValue(Control mControl, object oValue)
    {
        string sControlType = mControl.GetType().Name;
        object pValue = null;
        bool isLoading = ((FormBase)mControl.FindForm()).IsLoading;
        if (!isLoading)
            pValue = Control_GetValue(mControl);
        switch (sControlType)
        {
            case "TextBox":

            case "ToolStripTextBoxControl":
                TextBox_SetValue(mControl as TextBox, oValue);
                break;
            //case "MaskedTextBox":
            //    (mControl as MaskedTextBox).Text = Globals.Object_GetValue<string>(oValue);
            //    break;
            case "ComboBox":
            case "ToolStripComboBoxControl":
                //Combo_SetValue((ComboBox)mControl, oValue);
                break;
            case "RichTextBox":
                ((RichTextBox)mControl).Rtf = Globals.DB_GetString(oValue);
                break;
            case "CheckBox":
                ((CheckBox)mControl).Checked = Globals.Object_SetValueEx<bool>(oValue);
                break;
            case "CheckedListBox":
                if (oValue != null && oValue.GetType().IsArray)
                {
                    //CheckedListBox_SetValue(mControl, oValue as object[]);
                }
                else
                {
                    //CheckedListBox_SetValue(mControl, Globals.DB_GetString(oValue));
                }
                break;
            case "RadioButtonList":
                //((RadioButtonList)mControl).SelectedValue = oValue;
                break;
            default:
                throw new Exception("Control type '" + sControlType + "' is not support");
        }
        FormGlobals.FormControlExt ext = FormGlobals.Control_GetExtension(mControl);
        if (isLoading)
            ext.InitValue = oValue;
        ext.PrevValue = pValue;
        Control_SetExtension(mControl, ext);
    }

    public static void Control_ClearData(Control.ControlCollection arrControl)
    {
        Control[] arr = new Control[arrControl.Count];// Array.CreateInstance(typeof(Control), arrControl.Count);
        arrControl.CopyTo(arr, 0);
        Control_ClearData(arr);
    }

    /// <summary>
    /// Xóa dữ liệu của các control trên form, dùng được với điều kiện phải gọi hàm SetFormField khi init
    /// </summary>
    /// <param name="arrControl"></param>
    public static void Control_ClearData(params Control[] arrControl)
    {
        foreach (Control mControl in arrControl)
        {
            switch (mControl.GetType().Name)
            {
                case "TextBox":
                    //DirectCast(mControl, TextBox).Text = ""
                    TextBox_SetValue(mControl as TextBox, "");
                    break;
                case "ComboBox":
                    if (((ComboBox)mControl).Items.Count > 0)
                    {
                        ((ComboBox)mControl).SelectedIndex = 0;
                    }
                    break;
                case "ListBox":
                    if (!(mControl.Parent.Parent is Form))
                    {
                        ((ListBox)mControl).Items.Clear();
                    }
                    break;
                case "TreeView":
                    if (!(mControl.Parent.Parent is Form))
                    {
                        ((TreeView)mControl).Nodes.Clear();
                    }
                    break;
                case "CheckBox":
                    ((CheckBox)mControl).Checked = false;
                    break;
                case "Button":
                    break;
                case "DataGridView":
                    ((DataGridView)mControl).DataSource = null;
                    break;
                default:
                    if (mControl.HasChildren)
                    {
                        Control_ClearData(mControl.Controls);
                    }
                    break;
            }
        }
    }

    //Xóa dữ liệu của các control trong panel
    public static void Panel_ClearData(params Control[] arrControl)
    {
        foreach (Control objControl in arrControl)
        {
            Panel_ClearData(objControl);
        }
    }

    //Clear data khi nhập bản ghi mới
    public static void Panel_ClearData(Control objControl)
    {
        if (!objControl.HasChildren)
        {
            throw new Exception("Panel_ClearData not suppport control " + objControl.GetType().Name);
        }
        Control_ClearData(objControl.Controls);
        //For Each mControl As Control In objControl.Controls
        //    Select Case TypeName(mControl)
        //        Case "TextBox"
        //            'DirectCast(mControl, TextBox).Text = ""
        //            TextBox_SetValue(mControl, "")
        //        Case "ComboBox"
        //            If CType(mControl, ComboBox).Items.Count > 0 Then
        //                DirectCast(mControl, ComboBox).SelectedIndex = 0
        //            End If
        //        Case "ListBox"
        //            If Not TypeOf mControl.Parent.Parent Is Windows.Forms.Form Then
        //                DirectCast(mControl, ListBox).Items.Clear()
        //            End If
        //        Case "TreeView"
        //            If Not TypeOf mControl.Parent.Parent Is Windows.Forms.Form Then
        //                DirectCast(mControl, TreeView).Nodes.Clear()
        //            End If
        //        Case "CheckBox"
        //            DirectCast(mControl, CheckBox).Checked = False
        //        Case "Button"
        //        Case Else
        //            If mControl.HasChildren Then
        //                Panel_ClearData(mControl)
        //            End If
        //    End Select
        //Next
    }


    //public static void Control_FillData(Control.ControlCollection arrControl, DataRowEx objRowEx)
    //{
    //    Control_FillData(arrControl, objRowEx, null);
    //}

    //public static void Control_FillData(Control.ControlCollection arrControl, DataRowEx objRowEx, FormatInvoker customFormat)
    //{
    //    //Array arr = Array.CreateInstance(typeof(Control), arrControl.Count);
    //    //
    //    Control[] arr = new Control[arrControl.Count];
    //    arrControl.CopyTo(arr, 0);
    //    Control_FillData(arr, objRowEx, customFormat);
    //}

    //public static void Control_FillData(Control[] arrControl, DataRowEx objRowEx)
    //{
    //    Control_FillData(arrControl, objRowEx, null);
    //}

    public static void Control_FillData(Control[] arrControl, DataRowEx objRowEx, FormatInvoker customFormat)
    {
        foreach (Control mControl in arrControl)
        {
            string sControlType = mControl.GetType().Name;
            if (cs_Control_Input.Contains(sControlType))
            {
                if (objRowEx == null || !objRowEx.HasData)
                {
                    Control_SetValue(mControl, null);
                    continue;
                }
                if (!objRowEx.HasItem(mControl.Name.Substring(3)))
                    continue;
                object oValue = objRowEx.Item(mControl.Name.Substring(3));
                if ((customFormat != null))
                    customFormat.Invoke(mControl.Name.Substring(3).ToUpper(), ref oValue);
                Control_SetValue(mControl, oValue);
            }
            else if (mControl.HasChildren)
            {
                Control_FillData(mControl.Controls, objRowEx, customFormat);
            }
        }
    }


    //----------------------------------------handle cho panel-------------------------------------
    //--------------------------------------------------------------------------------------------
    #endregion

    public static ToolTip Form_GetToolTip(Form f)
    {
        Control ctlDummy = f.Controls[f.Name + "_ToolTip"];
        ToolTip objToolTip = default(ToolTip);
        if (ctlDummy == null)
        {
            ctlDummy = new Control();
            ctlDummy.Name = f.Name + "_ToolTip";
            f.Controls.Add(ctlDummy);
            objToolTip = new ToolTip();
            objToolTip.ToolTipIcon = ToolTipIcon.Info;
            objToolTip.IsBalloon = true;
            objToolTip.UseAnimation = true;
            objToolTip.UseFading = true;
            objToolTip.AutoPopDelay = 3000;
            ctlDummy.Tag = objToolTip;
        }
        else
        {
            objToolTip = ctlDummy.Tag as ToolTip;
        }
        return objToolTip;
    }


    //----------------------------------------handle cho grid-------------------------------------
    //--------------------------------------------------------------------------------------------
    #region handle cho grid


    //-----------
    //<Grid>
    //-----------

    //Kiểm tra dữ liệu trên Grid có bị lỗi không
    public static bool Grid_CheckValid(DataGridView objGrid)
    {
        DataTable mTable = default(DataTable);
        if (objGrid.DataSource is DataView)
        {
            mTable = ((DataView)objGrid.DataSource).Table;
        }
        else if (objGrid.DataSource is DataTable)
        {
            mTable = (DataTable)objGrid.DataSource;
        }
        else
        {
            return true;
        }
        foreach (DataRow mRow in mTable.GetErrors())
        {
            if (mRow.RowState != DataRowState.Deleted)
            {
                return false;
            }
        }
        return true;
    }

    //Init một cột mới trên Grid
    public static T Grid_NewColumn<T>(string headerText, string dataField, int colWidth)
    {
        T objColumn = Activator.CreateInstance<T>();
        Grid_FormatColumn((objColumn as DataGridViewColumn), headerText, dataField, colWidth, null);
        //
        return objColumn;
    }

    public static T Grid_NewColumn<T>(string headerText, string dataField, int colWidth, string format)
    {
        T objColumn = Activator.CreateInstance<T>();
        Grid_FormatColumn((objColumn as DataGridViewColumn), headerText, dataField, colWidth, format);
        //
        return objColumn;
    }

    public static T Grid_NewColumn<T>(string headerText, string dataField, int colWidth, string format, bool viewOnly)
    {
        T objColumn = Activator.CreateInstance<T>();
        Grid_FormatColumn((objColumn as DataGridViewColumn), headerText, dataField, colWidth, format);
        (objColumn as DataGridViewColumn).ReadOnly = viewOnly;
        //
        return objColumn;
    }

    //Public Function Grid_NewColumn(ByVal colType As GridColumnType _
    //                             , ByVal headerText As String _
    //                             , ByVal dataField As String _
    //                             , ByVal colWidth As Integer _
    //                             ) As DataGridViewColumn
    //    Return Grid_NewColumn(colType, headerText, dataField, colWidth, Nothing, False)
    //End Function

    //Public Function Grid_NewColumn(ByVal colType As GridColumnType _
    //                             , ByVal headerText As String _
    //                             , ByVal dataField As String _
    //                             , ByVal colWidth As Integer _
    //                             , ByVal format As String _
    //                             ) As DataGridViewColumn
    //    Return Grid_NewColumn(colType, headerText, dataField, colWidth, format, False)
    //End Function

    //Public Function Grid_NewColumn(ByVal colType As GridColumnType _
    //                             , ByVal headerText As String _
    //                             , ByVal dataField As String _
    //                             , ByVal colWidth As Integer _
    //                             , ByVal format As String _
    //                             , ByVal isReadOnly As Boolean _
    //                                ) As DataGridViewColumn
    //    Dim objColumn As DataGridViewColumn
    //    Select Case colType
    //        Case GridColumnType.ButtonColumn
    //            objColumn = New DataGridViewButtonColumn
    //        Case GridColumnType.CheckColumn
    //            objColumn = New DataGridViewCheckBoxColumn
    //        Case GridColumnType.ComboColumn
    //            objColumn = New DataGridViewComboBoxColumn
    //        Case Else
    //            objColumn = New DataGridViewTextBoxColumn
    //    End Select
    //    objColumn.ReadOnly = isReadOnly
    //    '
    //    Grid_FormatColumn(objColumn, headerText, dataField, colWidth, format)
    //    '
    //    Return objColumn
    //End Function

    public static void Grid_FormatColumn(DataGridViewColumn gridColumn, string headerText, string dataField, int colWidth)
    {
        Grid_FormatColumn(gridColumn, headerText, dataField, colWidth, null);
    }

    public static void Grid_FormatColumn(DataGridViewColumn gridColumn, string headerText, string dataField, int colWidth, string format)
    {
        gridColumn.HeaderText = headerText;
        if (dataField.Contains("."))
        {
            gridColumn.DataPropertyName = dataField.Split(new char[] { '.' })[1];
        }
        else
        {
            gridColumn.DataPropertyName = dataField;
        }
        gridColumn.Width = colWidth;
        gridColumn.Visible = (colWidth > 0);
        gridColumn.Name = dataField;
        if ((format != null))
            gridColumn.DefaultCellStyle.Format = format;
        if (gridColumn is DataGridViewCheckBoxColumn)
        {
            ((DataGridViewCheckBoxColumn)gridColumn).TrueValue = "1";
            ((DataGridViewCheckBoxColumn)gridColumn).FalseValue = "0";
        }
        else if (gridColumn is DataGridViewButtonColumn)
        {
            gridColumn.DataPropertyName = "";
            gridColumn.HeaderText = "";
            ((DataGridViewButtonColumn)gridColumn).Text = headerText;
            ((DataGridViewButtonColumn)gridColumn).UseColumnTextForButtonValue = true;
        }
    }

    public static DataGridHandle Grid_Init(DataGridView gridControl, List<DataGridViewColumn> arrColumn, string keyColumn)
    {
        return Grid_Init(gridControl, arrColumn, keyColumn, 0);
    }

    public static DataGridHandle Grid_Init(DataGridView gridControl, List<DataGridViewColumn> arrColumn, string keyColumn, int frozenCount)
    {
        return Grid_Init(gridControl, arrColumn, keyColumn, frozenCount, DataGridViewColumnSortMode.NotSortable);
    }

    public static DataGridHandle Grid_Init(DataGridView gridControl, List<DataGridViewColumn> arrColumn, string keyColumn, int frozenCount, DataGridViewColumnSortMode sortMode)
    {
        //
        if ((arrColumn != null))
        {
            foreach (DataGridViewColumn clm in arrColumn)
            {
                if (!(string.IsNullOrEmpty(clm.DataPropertyName)) && string.IsNullOrEmpty(clm.Name))
                {
                    clm.Name = clm.DataPropertyName;
                }
                if (clm.Name != "RN")
                {
                    clm.SortMode = sortMode;
                }
                else
                {
                    clm.SortMode = DataGridViewColumnSortMode.NotSortable;
                }
                clm.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleCenter;
            }
            gridControl.Columns.AddRange(arrColumn.ToArray());
        }
        //
        return Grid_Init(gridControl, keyColumn, frozenCount);
    }

    public static DataGridHandle Grid_Init(DataGridView gridControl, string keyColumn)
    {
        return Grid_Init(gridControl, keyColumn, 0);
    }

    public static DataGridHandle Grid_Init(DataGridView gridControl, string keyColumn, int frozenCount)
    {
        //
        gridControl.AutoGenerateColumns = false;
        //
        if (gridControl.Columns.Count > frozenCount)
        {
            for (int i = 0; i <= frozenCount - 1; i++)
            {
                gridControl.Columns[i].Frozen = true;
            }
        }
        //
        return new DataGridHandle(gridControl, keyColumn);
    }

    public static void Grid_BindCombo(DataGridViewComboBoxColumn clmCombo, string domainCode, string displayField, string firstItem)
    {
        DataTable dt = SystemController.Instance().Domain_GetDic(domainCode);
        Grid_BindCombo(clmCombo, dt, displayField, "Item_Code", firstItem);
    }

    public static void Grid_BindCombo(DataGridViewComboBoxColumn clmCombo, string domainCode, string firstItem)
    {
        Grid_BindCombo(clmCombo, domainCode, "Item_Value", firstItem);
    }

    public static void Grid_BindCombo(DataGridViewComboBoxColumn clmCombo, DataTable dataSource, string displayField, string valueField, string firstItem)
    {
        clmCombo.DisplayMember = displayField;
        clmCombo.ValueMember = valueField;
        if (!string.IsNullOrEmpty(firstItem))
        {
            DataRow mRow = ((DataTable)dataSource).NewRow();
            foreach (DataColumn mCol in mRow.Table.Columns)
            {
                mCol.AllowDBNull = true;
            }
            mRow[clmCombo.DisplayMember] = firstItem;
            if (clmCombo.DisplayMember != clmCombo.ValueMember)
            {
                mRow[clmCombo.ValueMember] = DBNull.Value;
                //COMBO_ITEM_NULL_VALUE
            }
            dataSource.Rows.InsertAt(mRow, 0);
        }
        clmCombo.DataSource = dataSource;
    }

    public static void Grid_FormatButtonColumn(DataGridViewButtonColumn clmButton)
    {
        clmButton.UseColumnTextForButtonValue = true;
        clmButton.HeaderText = "";
        clmButton.DefaultCellStyle.BackColor = System.Drawing.SystemColors.Control;
        clmButton.DefaultCellStyle.NullValue = clmButton.Text;
        clmButton.DefaultCellStyle.SelectionBackColor = System.Drawing.SystemColors.Control;
        clmButton.DefaultCellStyle.SelectionForeColor = System.Drawing.SystemColors.ControlText;
    }

    public static void Grid_SetColumnCopy(DataColumn objColumn, bool bSetOn = true)
    {
        if (bSetOn)
        {
            objColumn.Caption = objColumn.ColumnName;
        }
        else
        {
            objColumn.Caption = "HIDE";
        }
    }

    public static void Grid_SetColumnViewOnly(DataGridViewColumn objColumn, bool bSetOn = true)
    {
        objColumn.ReadOnly = bSetOn;
        if (bSetOn)
        {
            //đặt màu cho cột viewonly: light gray

            //
            objColumn.DefaultCellStyle.ForeColor = System.Drawing.Color.Gray;
            //objColumn.Tag = objColumn.DefaultCellStyle.BackColor

            //objColumn.DefaultCellStyle.BackColor = Color.LightGray;
        }
        else
        {
            objColumn.DefaultCellStyle.ForeColor = System.Drawing.Color.Black;
            objColumn.DefaultCellStyle.BackColor = Control.DefaultBackColor;
            //objColumn.Tag 
        }
    }

    public static void Grid_SetRowObject(DataGridViewRow objGridRow, Standard_Info objInfo)
    {
        Type mType = objInfo.GetType();
        DataGridView objGrid = objGridRow.DataGridView;
        foreach (System.Reflection.PropertyInfo mProperty in mType.GetProperties())
        {
            if (objGrid.Columns.Contains(mProperty.Name))
            {
                if (objGrid.Columns[mProperty.Name] is DataGridViewCheckBoxColumn)
                {
                    if (Globals.Object_GetValue<bool>(mProperty.GetValue(objInfo, null)))
                    {
                        objGridRow.Cells[mProperty.Name].Value = "1";
                    }
                    else
                    {
                        objGridRow.Cells[mProperty.Name].Value = "0";
                    }
                }
                else
                {
                    objGridRow.Cells[mProperty.Name].Value = Globals.DB_GetNull(mProperty.GetValue(objInfo, null));
                }
            }
            else
            {
                DataRow objRow = default(DataRow);
                try
                {
                    if (objGridRow.DataBoundItem is DataRowView)
                    {
                        objRow = ((DataRowView)objGridRow.DataBoundItem).Row;
                    }
                    else
                    {
                        objRow = (DataRow)objGridRow.DataBoundItem;
                    }
                }
                catch
                {
                    continue;
                }
                if (objRow.Table.Columns.Contains(mProperty.Name))
                {
                    if (mProperty.GetValue(objInfo, null) is bool)
                    {
                        if (Globals.Object_GetValue<bool>(mProperty.GetValue(objInfo, null)))
                        {
                            objRow[mProperty.Name] = "1";
                        }
                        else
                        {
                            objRow[mProperty.Name] = "0";
                        }
                    }
                    else
                    {
                        objRow[mProperty.Name] = Globals.DB_GetNull(mProperty.GetValue(objInfo, null));
                    }
                }
            }
        }
    }

    public static void Grid_SetRowObject(DataGridViewRow objGridRow, DataRowEx objRow)
    {
        Grid_SetRowObject(objGridRow, objRow, null);
    }

    public static void Grid_SetRowObject(DataGridViewRow objGridRow, DataRowEx objRowEx, string columnMapping)
    {
        Dictionary<string, string> dicMapping = new Dictionary<string, string>();
        if (!string.IsNullOrEmpty(columnMapping))
        {
            foreach (string sMapping in columnMapping.Split(new char[] { ';' }))
            {
                string[] arrColumn = sMapping.Split(new char[] { '=' });
                if (arrColumn.Length > 1)
                {
                    dicMapping.Add(arrColumn[0].Trim().ToUpper(), arrColumn[1]);
                }
            }
        }
        //
        DataGridView objGrid = objGridRow.DataGridView;
        DataRow objRowData = null;
        try
        {
            if (objGridRow.DataBoundItem is DataRowView)
            {
                objRowData = ((DataRowView)objGridRow.DataBoundItem).Row;
            }
            else
            {
                objRowData = (DataRow)objGridRow.DataBoundItem;
            }

        }
        catch
        {
        }
        //
        string rowKey = null;
        foreach (string dataKey in objRowEx.Data.Keys)
        {
            if (dicMapping.ContainsKey(dataKey.ToUpper()))
            {
                rowKey = dicMapping[dataKey.ToUpper()];
            }
            else
            {
                rowKey = dataKey;
            }
            if (objGrid.Columns.Contains(rowKey))
            {
                if (objGrid.Columns[rowKey] is DataGridViewCheckBoxColumn)
                {
                    if (Globals.Object_GetValue<bool>(objRowEx.Item(rowKey)))
                    {
                        objGridRow.Cells[rowKey].Value = "1";
                    }
                    else
                    {
                        objGridRow.Cells[rowKey].Value = "0";
                    }
                }
                else
                {
                    objGridRow.Cells[rowKey].Value = Globals.DB_GetNull(objRowEx.Item(dataKey));
                }
            }
            else
            {
                if (objRowData == null)
                    continue;
                if (objRowData.Table.Columns.Contains(rowKey))
                {
                    if (objRowEx.Item(dataKey) is bool)
                    {
                        if (Globals.Object_GetValue<bool>(objRowEx.Item(dataKey)))
                        {
                            objRowData[rowKey] = "1";
                        }
                        else
                        {
                            objRowData[rowKey] = "0";
                        }
                    }
                    else
                    {
                        objRowData[rowKey] = Globals.DB_GetNull(objRowEx.Item(dataKey));
                    }
                }
            }
        }
    }

    public static void Grid_GetRowObject(DataGridViewRow objGridRow, Standard_Info objInfo)
    {
        Type mType = objInfo.GetType();
        DataGridView objGrid = objGridRow.DataGridView;
        object objValue = null;
        foreach (System.Reflection.PropertyInfo mProperty in mType.GetProperties())
        {
            if (objGrid.Columns.Contains(mProperty.Name))
            {
                objValue = objGridRow.Cells[mProperty.Name].Value;
            }
            else
            {
                DataRow objRow = default(DataRow);
                try
                {
                    if (objGridRow.DataBoundItem is DataRowView)
                    {
                        objRow = ((DataRowView)objGridRow.DataBoundItem).Row;
                    }
                    else
                    {
                        objRow = (DataRow)objGridRow.DataBoundItem;
                    }
                }
                catch
                {
                    continue;
                }
                if (objRow.Table.Columns.Contains(mProperty.Name))
                {
                    objValue = objRow[mProperty.Name];
                }
                else
                {
                    continue;
                }
            }
            if (Globals.IsDBNull(objValue))
            {
                // translate Null value
                mProperty.SetValue(objInfo, Null.SetNull(mProperty), null);
            }
            else
            {
                if (mProperty.PropertyType.Name == "Boolean")
                {
                    mProperty.SetValue(objInfo, Convert.ToBoolean(objValue), null);
                }
                else
                {
                    mProperty.SetValue(objInfo, Convert.ChangeType(objValue, mProperty.PropertyType), null);
                }
            }
        }
    }

    public static void Grid_SetRowData(DataGridViewRow objRow, string columnName, object oValue)
    {
        if (objRow.DataBoundItem is DataRowView)
        {
            ((DataRowView)objRow.DataBoundItem)[columnName] = oValue;
        }
        else
        {
            objRow.Cells["clm" + columnName].Value = oValue;
        }
    }

    public static object Grid_GetRowData(DataGridViewRow objRow, string columnName)
    {
        if (objRow.DataBoundItem is DataRowView)
        {
            return ((DataRowView)objRow.DataBoundItem)[columnName];
        }
        else
        {
            return objRow.Cells["clm" + columnName].Value;
        }
    }

    public static void Grid_MoveSelect(DataGridView dtgSource, DataGridView dtgDest)
    {
        int iCount = dtgSource.SelectedRows.Count;
        while (dtgSource.SelectedRows.Count > 0)
        {
            DataGridViewRow dtgRow = dtgSource.SelectedRows[dtgSource.SelectedRows.Count - 1];
            if (dtgSource.DataSource is DataTable)
            {
                object[] arrItem = ((DataRowView)dtgRow.DataBoundItem).Row.ItemArray;
                ((DataTable)dtgDest.DataSource).Rows.Add(arrItem);
            }
            else if (dtgSource.DataSource is DataView)
            {
                object[] arrItem = ((DataRowView)dtgRow.DataBoundItem).Row.ItemArray;
                ((DataView)dtgDest.DataSource).Table.Rows.Add(arrItem);
            }
            else
            {
                dtgDest.Rows.Add(dtgRow.Clone());
            }
            dtgSource.Rows.Remove(dtgRow);
            iCount -= 1;
            if (iCount == 0)
            {
                dtgSource.ClearSelection();
                break; // TODO: might not be correct. Was : Exit While
            }
        }
    }

    public static void Grid_MoveAll(DataGridView dtgSource, DataGridView dtgDest)
    {
        int iCount = dtgSource.Rows.Count;
        while (dtgSource.Rows.Count > 0)
        {
            DataGridViewRow dtgRow = dtgSource.Rows[0];
            if (dtgSource.DataSource is DataTable)
            {
                object[] arrItem = ((DataRowView)dtgRow.DataBoundItem).Row.ItemArray;
                ((DataTable)dtgDest.DataSource).Rows.Add(arrItem);
            }
            else if (dtgSource.DataSource is DataView)
            {
                object[] arrItem = ((DataRowView)dtgRow.DataBoundItem).Row.ItemArray;
                ((DataView)dtgDest.DataSource).Table.Rows.Add(arrItem);
            }
            else
            {
                dtgDest.Rows.Add(dtgRow.Clone());
            }
            dtgSource.Rows.Remove(dtgRow);
            iCount -= 1;
            if (iCount == 0)
            {
                dtgSource.ClearSelection();
                break; // TODO: might not be correct. Was : Exit While
            }
        }
    }

    public static void Grid_SetRowDisplay(DataGridView ctlGrid, string sColumnName)
    {
        Grid_SetRowDisplay(ctlGrid, sColumnName, 100);
    }

    public static void Grid_SetRowDisplay(DataGridView ctlGrid, string sColumnName, int iMaxHeight)
    {
        foreach (DataGridViewRow dtgRow in ctlGrid.Rows)
        {
            if (ctlGrid.Columns.Contains("Order_Code"))
            {
                dtgRow.Cells["Order_Code"].Value = dtgRow.Index + 1;
            }
            dtgRow.Height = iMaxHeight;
            dtgRow.Height = dtgRow.Cells[sColumnName].GetContentBounds(dtgRow.Index).Height + 10;
        }
    }

    public static void Grid_SetCellValue(DataGridViewCell cell, object value)
    {
        if (cell.OwningRow.IsNewRow)
        {
            cell.DataGridView.CurrentCell = cell;
            cell.DataGridView.BeginEdit(false);
            cell.DataGridView.EditingControl.Text = Globals.DB_GetString(value);
            cell.DataGridView.EndEdit();
        }
        cell.Value = value;
    }


    public static bool Grid_HasError(System.Windows.Forms.DataGridView dgv)
    {
        bool hasErrorText = false;
        //replace this.dataGridView1 with the name of your datagridview control
        foreach (System.Windows.Forms.DataGridViewRow row in dgv.Rows)
        {
            foreach (System.Windows.Forms.DataGridViewCell cell in row.Cells)
            {
                if (cell.ErrorText.Length > 0)
                {
                    hasErrorText = true;
                    break;
                }
            }
            if (hasErrorText)
                break;
        }
        return hasErrorText;
    }


    public static void Grid_CopyPaste(DataGridView dgv, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.C)
        {
            DataObject d = dgv.GetClipboardContent();
            Clipboard.SetDataObject(d);
            e.Handled = true;
        }
        else if (e.Control && e.KeyCode == Keys.V)
        {
            string CopiedContent = Clipboard.GetText();
            string[] Lines = CopiedContent.Split('\n');
            int StartingRow = dgv.CurrentCell.RowIndex;
            int StartingColumn = dgv.CurrentCell.ColumnIndex;
            foreach (var line in Lines)
            {
                if (StartingRow <= (dgv.Rows.Count - 1))
                {
                    string[] cells = line.Split('\t');
                    int ColumnIndex = StartingColumn;
                    for (int i = 0; i < cells.Length && ColumnIndex <= (dgv.Columns.Count - 1); i++)
                    {
                        dgv[ColumnIndex++, StartingRow].Value = cells[i];
                    }
                    StartingRow++;
                }
            }
        }
    }

    //-----------
    //</Grid>
    //-----------

    //----------------------------------------handle cho panel-------------------------------------
    //--------------------------------------------------------------------------------------------
    #endregion

    public static string App_TempPath()
    {
        string sPath = Path.GetTempPath() + "\\" + Application.ProductName;
        if (!Directory.Exists(sPath))
            Directory.CreateDirectory(sPath);
        return sPath;
    }

    public static string App_TempFile(string sExt)
    {
        if (string.IsNullOrEmpty(sExt))
            sExt = "tmp";
        if (!sExt.StartsWith("."))
            sExt = "." + sExt;
        string sFile = Path.GetRandomFileName() + sExt;
        sFile = App_TempPath() + "\\" + sFile;
        return sFile;
    }

    public static void App_TempClear()
    {
        string sPath = App_TempPath();
        string[] filePaths = Directory.GetFiles(sPath);
        try
        {
            foreach (string filePath in filePaths)
            {
                File.Delete(filePath);
            }
        }
        catch
        {
        }
    }

    //public static object Find_Control(Control mParentControl, string sName)
    //{
    //    if (mParentControl.Controls.ContainsKey(sName))
    //    {
    //        return mParentControl.Controls[sName];
    //    }
    //    else
    //    {
    //        Control[] arrControl = mParentControl.Controls.Find(sName, true);
    //        if (arrControl.Length == 0)
    //            return null;
    //        return arrControl[0];
    //    }
    //}


    //Handle sự kiện default, khi nhấn enter
    public static void Control_SetDefault(Control objControl, Button defaultButton)
    {
        if (objControl is TextBox || objControl is ComboBox)
        {
            if (!(objControl.Tag is FormControlExt))
            {
                objControl.Tag = new FormControlExt();
            }
            FormControlExt mField = (FormControlExt)objControl.Tag;
            mField.DefaultButton = defaultButton;
            objControl.Tag = mField;
            objControl.KeyPress += Event_Key_Press;
        }
        else
        {
            switch (objControl.GetType().Name)
            {
                case "ToolStrip":
                    foreach (ToolStripItem item in ((ToolStrip)objControl).Items)
                    {
                        if (item is ToolStripTextBox)
                        {
                            Control_SetDefault(((ToolStripTextBox)item).TextBox, defaultButton);
                        }
                        else if (item is ToolStripComboBox)
                        {
                            Control_SetDefault(((ToolStripComboBox)item).ComboBox, defaultButton);
                        }
                    }

                    break;
                default:
                    foreach (Control item in objControl.Controls)
                    {
                        if (item is TextBox)
                        {
                            Control_SetDefault((TextBox)item, defaultButton);
                        }
                    }

                    break;
            }
        }
    }


    //
    public static void Control_SetDefault(Control objControl, EventHandler defaultHandle)
    {
        if (objControl is TextBox || objControl is ComboBox)
        {
            if (!(objControl.Tag is FormControlExt))
            {
                objControl.Tag = new FormControlExt();
            }
            FormControlExt mField = (FormControlExt)objControl.Tag;
            mField.DefaultHandle = defaultHandle;
            objControl.Tag = mField;
            objControl.KeyPress += Event_Key_Press;
        }
        else
        {
            switch (objControl.GetType().Name)
            {
                case "ToolStrip":
                    foreach (ToolStripItem item in ((ToolStrip)objControl).Items)
                    {
                        if (item is ToolStripTextBox)
                        {
                            Control_SetDefault(((ToolStripTextBox)item).TextBox, defaultHandle);
                        }
                        else if (item is ToolStripComboBox)
                        {
                            Control_SetDefault(((ToolStripComboBox)item).ComboBox, defaultHandle);
                        }
                    }

                    break;
                default:
                    foreach (Control item in objControl.Controls)
                    {
                        if (item is TextBox)
                        {
                            Control_SetDefault((TextBox)item, defaultHandle);
                        }
                    }

                    break;
            }
        }
    }

    /// <summary>
    /// Sự kiện nhấn phím
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private static void Event_Key_Press(object sender, KeyPressEventArgs e)
    {
        if (e.KeyChar.ToString() == Globals.vbCr)
        {
            if ((sender as Control).Tag is FormControlExt)
            {
                e.Handled = true;
                //
                Control_ForceValidate(sender as Control);
                //
                FormControlExt mField = (FormControlExt)(sender as Control).Tag;
                if (mField.DefaultHandle != null)
                    mField.DefaultHandle.Invoke(sender, null);
                if (mField.DefaultButton != null)
                    mField.DefaultButton.PerformClick();
            }
        }
    }

    internal static void Control_ForceValidate(Control sender)
    {
        Type type = sender.GetType();
        type.InvokeMember("PerformControlValidation", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, sender, new object[] { true });
    }


    public void Control_NextFocus(Control objControl)
    {
        Control objForm = objControl.Parent;
        Control objNext = objForm.GetNextControl(objControl, true);
        while ((objNext != null))
        {
            switch (objNext.GetType().Name)
            {
                case "TextBox":
                case "ComboBox":
                    objNext.Focus();
                    break; // TODO: might not be correct. Was : Exit While
                default:
                    objNext = objForm.GetNextControl(objNext, true);
                    break;
            }
        }
    }

    public static void Control_FirstFocus(Control objControl)
    {
        Control objNext = objControl.GetNextControl(null, true);
        bool bFound = false;
        while ((objNext != null))
        {
            switch (objNext.GetType().Name)
            {
                case "TextBox":
                case "ToolStripTextBox":
                    bFound = objNext.Enabled && !((TextBox)objNext).ReadOnly;
                    break;
                case "ComboBox":
                case "ToolStripComboBox":
                    bFound = objNext.Enabled;
                    break;
                case "TabControl":
                    Control_FirstFocus(((TabControl)objNext).SelectedTab);
                    break;
                case "ToolStrip":
                    if (ToolStrip_FirstFocus(objNext as ToolStrip))
                    {
                        break; // TODO: might not be correct. Was : Exit While
                    }
                    break;
                case "DataGridView":
                    break;
                //Nothing
                default:
                    if (objNext.HasChildren)
                    {
                        Control_FirstFocus(objNext);
                        break; // TODO: might not be correct. Was : Exit While
                    }
                    break;
            }
            if (bFound && objNext.TabStop)
            {
                objNext.Focus();
                break; // TODO: might not be correct. Was : Exit While
            }
            objNext = objControl.GetNextControl(objNext, true);
        }
    }

    private static bool ToolStrip_FirstFocus(ToolStrip objToolStrip)
    {
        bool bFound = false;
        foreach (ToolStripItem objNext in objToolStrip.Items)
        {
            switch (objNext.GetType().Name)
            {
                case "TextBox":
                case "ToolStripTextBox":
                    bFound = objNext.Enabled && !((ToolStripTextBox)objNext).ReadOnly;
                    if (bFound)
                        ((ToolStripTextBox)objNext).Focus();
                    break;
                case "ComboBox":
                case "ToolStripComboBox":
                    bFound = objNext.Enabled;
                    if (bFound)
                        ((ToolStripComboBox)objNext).Focus();
                    break;
            }
            if (bFound)
            {
                //objNext.Focus()
                break; // TODO: might not be correct. Was : Exit For
            }
        }
        return bFound;
    }

    //public List<T> Control_ListOfType<T>(Control objParent)
    //{
    //    List<T> retVal = new List<T>();
    //    foreach (Control ctl in objParent.Controls)
    //    {
    //        if (ctl is T)
    //        {
    //            retVal.Add(ctl as T);
    //        }
    //        else if (ctl.HasChildren)
    //        {
    //            retVal.AddRange(Control_ListOfType<TheControlType>(ctl).ToArray());
    //        }
    //    }
    //    return retVal;
    //}


    //Init_Khi khởi động ứng dụng
    public static void App_Init()
    {
        try
        {
            //DataRowEx drConstant = SystemController.Instance().SysParam_SelectGroup("CONSTANT");
            //Keys lookupKey = Keys_Parse(drConstant.GetValue<string>("CS_LOOKUP_KEY"));
            //if (lookupKey != Keys.None)
            //    CS_LOOKUP_KEY = lookupKey;
            ////Get system hotkey define
            //HotKeyData = SystemController.Instance().SysParam_SelectGroup("HOTKEY");
            //Init main thread
            Globals.Application_SetCultureInfo(System.Threading.Thread.CurrentThread);
        }
        catch (Exception ex)
        {
            FormGlobals.Message_Error(ex);
        }
    }


    internal static Keys Keys_Parse(string sText)
{
	Keys key = Keys.None;
	if (string.IsNullOrEmpty(sText))
		return key;
	string[] arrKey = sText.Split(new string[]{"+"},StringSplitOptions.None);
	foreach (string sKey_loopVariable in arrKey) 
    {
		//sKey = sKey_loopVariable;
        switch (sKey_loopVariable)
        {
			case "Ctrl":
				key = key | Keys.Control;
				break;
			case "Alt":
				key = key | Keys.Alt;
				break;
			case "F1":
				key = key | Keys.F1;
				break;
			case "F2":
				key = key | Keys.F2;
				break;
			case "F3":
				key = key | Keys.F3;
				break;
			case "F4":
				key = key | Keys.F4;
				break;
			case "F5":
				key = key | Keys.F5;
				break;
			case "F6":
				key = key | Keys.F6;
				break;
			case "F7":
				key = key | Keys.F7;
				break;
			case "F8":
				key = key | Keys.F8;
				break;
			case "F9":
				key = key | Keys.F9;
				break;
			case "F10":
				key = key | Keys.F10;
				break;
			case "F11":
				key = key | Keys.F11;
				break;
			case "F12":
				key = key | Keys.F12;
				break;
			case "A": // TODO: to "Z"
				//key = key | Strings.Asc(sKey);
				break;
			default:
				break; // TODO: might not be correct. Was : Exit For

				break;
		}
	}
	//
	return key;
}

    /// <summary>
    /// Gán giá trị tất cả textbox trong nhóm control = giá trị value.ToString() truyền vào
    /// </summary>
    public static void TextBox_SetValue_AllChild(object value, params Control[]groupControl)
    {
        foreach(Control ctr in groupControl)
        {
            if (ctr.HasChildren)
            {
                foreach(Control ctrChild in ctr.Controls)
                    TextBox_SetValue_AllChild(value, ctrChild);
            }
            else if (ctr is TextBox)
            {
                ctr.Text = value.ToString();
            }
        }
    }




    public static EventHandler cbo_DropDown { get; set; }


    /// <summary>
    /// Add nút xuất ra excel đối với datagridview, vị tri trên phải
    /// </summary>
    /// <param name="dgvList"></param>
    public static void DataGridView_AddExcelIcon(params DataGridView[] dgvList)
    {
        int i = 0;
        foreach (DataGridView dgv in dgvList)
        {
            i++;
            //
            Button btn = new Button();
            btn.Name = "btnExportExcel" + i.ToString();
            btn.Text = "Xuất Excel";
            btn.Width = 90;
            btn.Height = 30;
            btn.FlatStyle = FlatStyle.Flat;
            btn.FlatAppearance.BorderSize = 1;
            btn.FlatAppearance.BorderColor = Color.DarkOrange;
            btn.ForeColor = Color.DarkOrange;
            btn.Anchor = (AnchorStyles.Right | AnchorStyles.Top);
            btn.BackColor = Color.Transparent;

            btn.ImageAlign = ContentAlignment.MiddleLeft;
            btn.TextAlign = ContentAlignment.MiddleRight;
            btn.Image = HRM.Common.Properties.Resources.gridExcel;
            btn.Top = 0 + 5;
            btn.Left = dgv.Width - btn.Width - 5;

            dgv.Scroll += new ScrollEventHandler(delegate(object sender, ScrollEventArgs e) {
                btn.Invalidate();
            });
            btn.Click += new EventHandler(delegate(object sender, EventArgs e)
            {
                string fileName = ExcelHelper.Excel_Export(dgv);
                if (!String.IsNullOrEmpty(fileName))
                {
                    try
                    {
                        System.Diagnostics.Process.Start(fileName);
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("Không mở được File \n" + Path.GetTempPath() + "\\" + fileName, "Thông báo");
                    }
                }
            });
            dgv.Controls.Add(btn);
            btn.BringToFront();
        }
    }
}


